- Path intersection
Given an array x containing n positive numbers. Starting at point (0,0), first move x[0] meters north, then x[1] meters west, x[2] meters south, x[3] meters east, and continue moving. In other words, your position will change counterclockwise after each movement.
Write a one-pass scanning algorithm with O(1) space complexity to determine whether the paths you travel through intersect.
The key to this question is to draw a picture to analyze the situation where various types will intersect, and finally summarize the solution
class Solution {
public:
bool isSelfCrossing(vector<int>& x) {
int x_size=x.size();
for (int i=3;i<x_size;++i)
{
if (i>=3 && x.at(i-1)<=x.at(i-3) && x.at(i)>=x.at(i-2))
return true;
if (i>=4 && x.at(i-3)==x.at(i-1) && x.at(i)+x.at(i-4)>=x.at(i-2))
return true;
if (i>=5 && x.at(i)+x.at(i-4)>=x.at(i-2) && x.at(i-1)+x.at(i-5)>=x.at(i-3)
&& x.at(i-2)>x.at(i-4) && x.at(i-3)>x.at(i-1))
return true;
}
return false;
}
};
- A palindrome pair is
given a group of different words, find all the different index pairs (i, j), so that the two words in the list, words[i] + words[j], can be spliced into a palindrome string .
The main focus of this question is: if s1 + s2 can form a palindrome pair, then either s1 is long or s2 is long or two are equal in length. The long one must have palindrome substrings and the other one-time reverse order. You can use a horse-drawn cart or brute force search to find a substring palindrome, and you can use a hash table or letter number to store other strings in reverse order
struct Trie {
struct node {
int ch[26];
int flag;
node() {
flag = -1;
memset(ch, 0, sizeof(ch));
}
};
vector<node> tree;
Trie() {
tree.emplace_back(); }
void insert(string& s, int id) {
int len = s.length(), add = 0;
for (int i = 0; i < len; i++) {
int x = s[i] - 'a';
if (!tree[add].ch[x]) {
tree.emplace_back();
tree[add].ch[x] = tree.size() - 1;
}
add = tree[add].ch[x];
}
tree[add].flag = id;
}
vector<int> query(string& s) {
int len = s.length(), add = 0;
vector<int> ret(len + 1, -1);
for (int i = 0; i < len; i++) {
ret[i] = tree[add].flag;
int x = s[i] - 'a';
if (!tree[add].ch[x]) {
return ret;
}
add = tree[add].ch[x];
}
ret[len] = tree[add].flag;
return ret;
}
};
class Solution {
public:
vector<pair<int, int>> manacher(string& s) {
int n = s.length();
string tmp = "#";
tmp += s[0];
for (int i = 1; i < n; i++) {
tmp += '*';
tmp += s[i];
}
tmp += '!';
int m = n * 2;
vector<int> len(m);
vector<pair<int, int>> ret(n);
int p = 0, maxn = -1;
for (int i = 1; i < m; i++) {
len[i] = maxn >= i ? min(len[2 * p - i], maxn - i) : 0;
while (tmp[i - len[i] - 1] == tmp[i + len[i] + 1]) {
len[i]++;
}
if (i + len[i] > maxn) {
p = i, maxn = i + len[i];
}
if (i - len[i] == 1) {
ret[(i + len[i]) / 2].first = 1;
}
if (i + len[i] == m - 1) {
ret[(i - len[i]) / 2].second = 1;
}
}
return ret;
}
vector<vector<int>> palindromePairs(vector<string>& words) {
Trie trie1, trie2;
int n = words.size();
for (int i = 0; i < n; i++) {
trie1.insert(words[i], i);
string tmp = words[i];
reverse(tmp.begin(), tmp.end());
trie2.insert(tmp, i);
}
vector<vector<int>> ret;
for (int i = 0; i < n; i++) {
const vector<pair<int, int>>& rec = manacher(words[i]);
const vector<int>& id1 = trie2.query(words[i]);
reverse(words[i].begin(), words[i].end());
const vector<int>& id2 = trie1.query(words[i]);
int m = words[i].size();
int all_id = id1[m];
if (all_id != -1 && all_id != i) {
ret.push_back({
i, all_id});
}
for (int j = 0; j < m; j++) {
if (rec[j].first) {
int left_id = id2[m - j - 1];
if (left_id != -1 && left_id != i) {
ret.push_back({
left_id, i});
}
}
if (rec[j].second) {
int right_id = id1[j];
if (right_id != -1 && right_id != i) {
ret.push_back({
i, right_id});
}
}
}
}
return ret;
}
};
- House Robber 3
Dynamic programming is solvable, and each node can be selected or not. If you don't select it, you can select its child nodes, otherwise you can't.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
struct SubtreeStatus {
int selected;
int notSelected;
};
class Solution {
public:
SubtreeStatus dfs(TreeNode* o) {
if (!o) {
return {
0, 0};
}
auto l = dfs(o->left);
auto r = dfs(o->right);
int selected = o->val + l.notSelected + r.notSelected;
int notSelected = max(l.selected, l.notSelected) + max(r.selected, r.notSelected);
return {
selected, notSelected};
}
int rob(TreeNode* o) {
auto rootStatus = dfs(o);
return max(rootStatus.selected, rootStatus.notSelected);
}
};
- Bit count
Given a non-negative integer num. For each number i in the range 0 ≤ i ≤ num, count the number of 1s in its binary number and return them as an array.
For a number and one-half of it, it is actually a shift operation. The difference in the number of numbers 1 is the last digit, so the bit operation can be used.
class Solution {
public:
vector<int> countBits(int num) {
vector<int> ret(num + 1);
for (int i = 1; i <= num; ++i)
ret[i] = ret[i >> 1] + (i & 1); // x / 2 is x >> 1 and x % 2 is x & 1
return ret;
}
};
- The flattened nested list iterator
gives you a nested list of integers. Please design an iterator so that it can traverse all integers in this integer list. Each item in the list is either an integer or another list. The elements of the list may also be integers or other lists
Traverse it once
class NestedIterator {
public:
vector<int> data;
vector<int>::iterator it;
NestedIterator(vector<NestedInteger> &nestedList) {
parse(nestedList);
it = data.begin();
}
void parse(vector<NestedInteger> &nestedList){
for(auto nes : nestedList){
if(nes.isInteger()) data.push_back(nes.getInteger());
else parse(nes.getList());
}
}
int next() {
return *it++;
}
bool hasNext() {
return it != data.end();
}
};
- Power of 4
Given an integer (32-bit signed integer), write a function to determine whether it is a power of 4.
The power of 4 must be the power of 2, but the power of 2 is not necessarily the power of 4. Through the binary of the power of 4, it can be found that the power of 4 in the binary number 1 only appears in odd numbers. Bit. Therefore, it is possible to perform the AND operation on the numbers (1010101010101010101010101010101) where the odd digits are all 1, and the even numbers are all 0, and the result is still the original number.
class Solution {
public:
bool isPowerOfFour(int num) {
return num > 0 && !(num & (num - 1)) && (num & 0x55555555) == num;
}
};
- Integer Splitting
Given a positive integer n, split it into the sum of at least two positive integers, and maximize the product of these integers. Returns the largest product you can get.
This problem can be solved by a greedy algorithm, but the best solution is definitely to derive the mathematical law and directly seek the maximum value
class Solution {
public:
int integerBreak(int n) {
if (n <= 3) {
return n - 1;
}
int quotient = n / 3;
int remainder = n % 3;
if (remainder == 0) {
return (int)pow(3, quotient);
} else if (remainder == 1) {
return (int)pow(3, quotient - 1) * 4;
} else {
return (int)pow(3, quotient) * 2;
}
}
};