# An analysis of leetcode's solution to 214-220 questions

Posted by manmanman on Thu, 25 Jun 2020 11:58:16 +0200

1. 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;
}
};
```
1. 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;
}
};

```
1. 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);
}
};

```
1. 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;
}
};
```
1. 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, -e)); // critical point, left corner
all.insert(make_pair(e, e)); // 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 != maxHeight) {
// Update last and add result set
last = p.first;
last = maxHeight;
res.push_back(last);
}
}

return res;
}
};

```
1. 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;
}
};
```
1. 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, 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;
}
};

```

Topics: less