- Shortest palindrome string
Given a string s, you can convert it to a palindrome string by adding characters before the string. Find and return the shortest palindrome string that can be converted in this way.
You can use horse drawn cart to get the longest palindrome substring, and then add it in reverse. It can also be solved by KMP
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; } };
- The K-th largest element in the array
The k-th largest element was found in the unsorted array. Note that you need to look for the k-th largest element after array sorting, not the k-th different element.
When you see the K elements, you know that the heap can be solved. In addition, you can use the selection algorithm. The idea of selecting 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; } //Find the smallest number in 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); //Element with current result small int currentResult = cut - left + 1; if (target == currentResult) { return nums[cut]; } else if (target < currentResult) { return select(nums, left, cut - 1, target); } else { //Find the next small number of 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 points to the leftmost number of the heap, and j points to the number of the next judgment 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; } };
- Combined sum 3
Find out the combination of all k numbers whose sum is n. Only positive integers of 1 - 9 are allowed in a combination, and there are no duplicate numbers in each combination.
This problem can be easily solved by backtracking
class Solution { public: vector<vector<int>> combinationSum3_dfs(int k, int n, int now, int status) { if(k == 0 && n == 0) { //A useful result 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) { //The condition of continuous dfs auto r = combinationSum3_dfs(k - 1, n - now, now + 1, status | (2 << now)); res.insert(res.end(), r.begin(), r.end()); //Result merging now++; } return res; } vector<vector<int>> combinationSum3(int k, int n) { return combinationSum3_dfs(k, n, 1, 0); } };
- There are duplicate elements
Given an array of integers, determine whether there are duplicate elements.
If any value appears in the array at least twice, the function returns true. Returns false if each element in the array is different.
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; } };
- The problem of skyline
There are many solutions to this problem: the most intuitive solution is to scan the scanning line from left to right once, compare the various heights saved in the current X-axis, and output the highest value. In the same way, we can use double linked list to scan. In addition, we can also adopt the idea of divide and Conquer: no building is 0, one building is the value, and many buildings are divided and conquer.
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}); // Saves all heights in the current location. vector<int> last = {0, 0}; // Saves the abscissa and height of the previous position for (auto& p : all) { if (p.second < 0) heights.insert(-p.second); // Left end, height in pile else heights.erase(heights.find(p.second)); // Right endpoint, remove height // Current key, maximum height auto maxHeight = *heights.rbegin(); // If the current maximum height is different from the previous height, it means that this is a turning point if (last[1] != maxHeight) { // Update last and add result set last[0] = p.first; last[1] = maxHeight; res.push_back(last); } } return res; } };
- Duplicate element 2 present
Given an integer array and an integer k, it is determined 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.
It's as simple as the first problem. The hash table is solved directly, but here's an optimization detail: we don't need to store all the numbers, just 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; } };
- Duplicate element 3 present
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 the absolute value satisfying the difference between I and j is also less than or equal to.
Returns true if it exists, and false if it does not exist.
There are many ways to solve this problem. The best way 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; } };