Analysis of Leetcode Problem Solving Ideas (30) 214-220

  1. The shortest palindrome string
    Given a string s, you can convert it into a palindrome string by adding characters in front of the string. Find and return the shortest palindrome that can be converted in this way.

In this question, you can use a horse-drawn cart to get the longest palindrome substring, and then add it in reverse. KMP can also be used to solve

class Solution {
    
    
public:
    string shortestPalindrome(string s)
    {
    
    
        int n = s.size();
        string rev(s);
        reverse(rev.begin(), rev.end());
        string s_new = s + "#" + rev;
        int n_new = s_new.size();
        vector<int> f(n_new, 0);
        for (int i = 1; i < n_new; i++) {
    
    
            int t = f[i - 1];
            while (t > 0 && s_new[i] != s_new[t])
                t = f[t - 1];
            if (s_new[i] == s_new[t])
                ++t;
            f[i] = t;
        }
        return rev.substr(0, n - f[n_new - 1]) + s;
    }
};
  1. Kth largest element
    in the array Find the kth largest element in the unsorted array. Please note that what you need to find is the k-th largest element after sorting the array, not the k-th different element.

Seeing K elements, you know that the heap can be resolved, and you can also use the selection algorithm to solve it. The idea of ​​choosing an algorithm is to divide and conquer

#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;

class Solution
{
    
    
public:
    int findKthLargest(vector<int> &nums, int k)
    {
    
    
        int result = 0;
        int numsSize = int(nums.size());
        if (numsSize == 0 || k > numsSize)
        {
    
    
            return 0;
        }
        //寻找第kMIN小的数
        int kMin = numsSize - k + 1;
        result = select(nums, 0, numsSize - 1, kMin);
        return result;
    }

    int select(vector<int> &nums, int left, int right, int target)
    {
    
    
        if (left == right)
        {
    
    
            return nums[left];
        }
        int cut = partition(nums, left, right);
        //当前第currentResult小的元素
        int currentResult = cut - left + 1;
        if (target == currentResult)
        {
    
    
            return nums[cut];
        }
        else if (target < currentResult)
        {
    
    
            return select(nums, left, cut - 1, target);
        }
        else
        {
    
    
            //寻找接下来第target - currentResult小的数
            return select(nums, cut + 1, right, target - currentResult);
        }
        return 0;
    }

    int partition(vector<int> &nums, int left, int right)
    {
    
    
        int cut = nums[right];
        //i指向大堆的最左边的数,j指向下一个判断的数
        int i = left;
        for (int j = left; j < right; j++)
        {
    
    
            if (nums[j] <= cut)
            {
    
    
                exchange(nums[i], nums[j]);
                i++;
            }
        }
        exchange(nums[i], nums[right]);
        return i;
    }

    void exchange(int &a, int &b)
    {
    
    
        int tmpInt = a;
        a = b;
        b = tmpInt;
        return;
    }
};

  1. Combination sum 3
    finds all k combinations that add up to n. Only positive integers from 1 to 9 are allowed in the combination, and there are no repeated numbers in each combination.

This question can be easily solved using the backtracking method

class Solution {
    
    
public:
    vector<vector<int>> combinationSum3_dfs(int k, int n, int now, int status) {
    
    
        if(k == 0 && n == 0) {
    
      //一个有用的结果
            vector<int> res;
            for(int i = 1; i < 10; i++) {
    
    
                if((2 << i) & status) res.push_back(i);
            }
            return {
    
    res};
        }
        vector<vector<int>> res;
        while(now < 10 && n >= now) {
    
       //能够继续dfs的条件
            auto r = combinationSum3_dfs(k - 1, n - now, now + 1, status | (2 << now));
            res.insert(res.end(), r.begin(), r.end()); //结果合并
            now++;
        }
        return res;
    }
    vector<vector<int>> combinationSum3(int k, int n) {
    
    
        return combinationSum3_dfs(k, n, 1, 0);
    }
};

  1. There are duplicate elements
    Given an integer array, judge whether there are duplicate elements.
    If any value appears at least twice in the array, the function returns true. If every element in the array is different, false is returned.

Very simple question, hash table storage and search

class Solution {
    
    
public:
    bool containsDuplicate(vector<int>& nums) {
    
    
        std::unordered_map<int, int> map;
        for (auto i : nums)
        {
    
    
            map[i]++;
            if (map[i] > 1)
                return true;
        }
        return false;
    }
};
  1. Skyline problem

There are many solutions to this problem: the most intuitive solution is to take the scan line to scan from left to right, compare the heights saved in the current X axis, and output the highest value. Similarly, we can also use a doubly linked list to scan. In addition, the idea of ​​divide and conquer can also be adopted: if there is no building, the value is 0, if there is one building, the value is divided and conquered.

class Solution {
    
    
public:
    vector<vector<int>> getSkyline(vector<vector<int>>& buildings) {
    
    
        multiset<pair<int, int>> all;
        vector<vector<int>> res;
        
        for (auto& e : buildings) {
    
    
            all.insert(make_pair(e[0], -e[2])); // critical point, left corner
            all.insert(make_pair(e[1], e[2])); // critical point, right corner
        }
        
        multiset<int> heights({
    
    0}); // 保存当前位置所有高度。
        vector<int> last = {
    
    0, 0}; // 保存上一个位置的横坐标以及高度
        for (auto& p : all) {
    
    
            if (p.second < 0) heights.insert(-p.second); // 左端点,高度入堆
            else heights.erase(heights.find(p.second)); // 右端点,移除高度
            
            // 当前关键点,最大高度
            auto maxHeight = *heights.rbegin();
            
            // 当前最大高度如果不同于上一个高度,说明这是一个转折点
            if (last[1] != maxHeight) {
    
    
                // 更新 last,并加入结果集
                last[0] = p.first;
                last[1] = maxHeight;
                res.push_back(last);
            }
        }
        
        return res;
    }
};

  1. There are duplicate elements 2
    Given an integer array and an integer k, judge whether there are two different indexes i and j in the array, so that nums [i] = nums [j], and the absolute value of the difference between i and j is at most k.

As simple as the first question, the hash table is solved directly, but here is an optimization detail: we don’t need to store all the numbers, we only need to use a sliding window of size k.

class Solution {
    
    
public:
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
    
    
        unordered_map<int, vector<int>> map;
        for (int i = 0; i < nums.size(); i++)
        {
    
    
            map[nums[i]].push_back(i);
            if (map[nums[i]].size() > 1)
            {
    
    
                for (int j = 1; j < map[nums[i]].size(); j++)
                {
    
    
                    if (map[nums[i]][j] - map[nums[i]][j - 1] <= k)
                        return true;
                }
            }
        }
        return false;
    }
};
  1. There are duplicate elements 3
    In the integer array nums, whether there are two subscripts i and j, so that the absolute value of the difference between nums [i] and nums [j] is less than or equal to t, and satisfies the absolute value of the difference between i and j Less than or equal to K.
    Return true if it exists, false if it does not exist.

There are many ways to solve this problem. The more excellent method is the idea of ​​bucket sorting or the way of sliding window.

class Solution {
    
    
public:
    bool containsNearbyAlmostDuplicate(vector<int>& nums, int k, int t) {
    
    
        if (k < 1 || t < 0 || nums.empty()) return false;
        int N = nums.size();
        map<long, int> m{
    
    {
    
    nums[0], 1}};
        for (int i = 1; i < N; ++i) {
    
    
            auto it = m.lower_bound(nums[i]);
            if (it != m.end() && abs(it->first - (long)nums[i]) <= t) return true;
            if (it != m.begin() && abs((--it)->first - (long)nums[i]) <= t)  return true;
            ++m[nums[i]];
            if (i - k >= 0 && --m[nums[i - k]] == 0) m.erase(nums[i - k]);
        }
        return false;
    }
};



Guess you like

Origin blog.csdn.net/u013354486/article/details/106805064