本题的关键在于画图分析各种类型会相交的情况,最后总结成解法
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;
}
};
本题主要关注点在于:如果s1 + s2可以构成回文对,那么要么s1长要么s2长要么两个等长。长的一个一定有回文子串以及另一个单次的逆序。查找子串回文串可以用马拉车或者暴力搜索,存储其他串逆序可以用哈希表或者字母数
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;
}
};
动态规划可解,每个节点可以选择或者不选。如果不选则可以选其子节点,否则不可以。
/**
* 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);
}
};
对于一个数字和它的二分之一,其实就是移位操作,带来的数字1的个数的差别就在于最后一位,因此采取位操作即可
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;
}
};
遍历一遍即可
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();
}
};
4的次方数一定是2的次方数,但2的次方数不一定是4的次方数,通过4的次方数二进制可以发现4的次方数二进制中1只出现在奇数位。因此可以通过于奇数位都是1,偶数为都是0的数(1010101010101010101010101010101)进行与运算,结果仍为原来数。
class Solution {
public:
bool isPowerOfFour(int num) {
return num > 0 && !(num & (num - 1)) && (num & 0x55555555) == num;
}
};
本题可以用贪心算法求解,但是最佳解决方案肯定是推导数学规律直接求最大值
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;
}
}
};