第一感觉,只要所有的数字相同,就可以翻转得到。证明略。。。
class Solution {
public:
bool canBeEqual(vector<int>& target, vector<int>& arr) {
if(target.size() != arr.size()) return false;
sort(target.begin(), target.end());
sort(arr.begin(), arr.end());
for(int i = 0; i < target.size(); i ++){
if(target[i] != arr[i]) return false;
}
return true;
}
};
把字符串中长度为k的子串,全部转换成十进制数字,然后看这些数字是否是 0 , 1 , 2 , . . . , 2 k − 1 0,1,2,...,2^k-1 0,1,2,...,2k−1。
看了别人的题解,直接比较不同的长度为 k k k的子串的个数是不是 2 k 2^k 2k个,简便不少。
class Solution {
public:
int string_to_int(string s){
int len = s.length();
int ret = 0;
int k = 1;
for(int i = len-1; i >= 0; i --){
ret += (s[i] - '0') * k;
k *= 2;
}
return ret;
}
bool hasAllCodes(string s, int k) {
set<int> si;
for(int i = 0; i + k <= s.length(); i ++){
// cout << string_to_int(s.substr(i, k)) << endl;
si.insert(string_to_int(s.substr(i, k)));
}
int n = pow(2, k);
for(int i = 0; i < n; i ++){
if(si.find(i) == si.end()) return false;
}
return true;
}
};
把 a i a_i ai课程的所有先修课程找出来,再把这些 a i a_i ai的先修课程更新到之前,以 a i a_i ai为先修课程的其他课程中去。再进行query。
之前有想过用并查集,但是并查集每个节点只有一个父亲,这个题中,每个节点都可以有多个父亲,就放弃了用并查集。
class Solution {
public:
vector<bool> checkIfPrerequisite(int n, vector<vector<int>>& prerequisites, vector<vector<int>>& queries) {
set<int> si[100];
for(int i = 0; i < prerequisites.size(); i ++){
vector<int> vi;
int a = prerequisites[i][1];
int b = prerequisites[i][0];
si[a].insert(b);
vi.push_back(b);
for(set<int>::iterator it = si[b].begin(); it != si[b].end(); it ++){
si[a].insert(*it);
vi.push_back(*it);
}
for(int i = 0; i < n; i ++){
if(si[i].find(a) == si[i].end()) continue;
for(int j = 0; j < vi.size(); j ++){
si[i].insert(vi[j]);
}
}
}
vector<bool> vb;
for(int i = 0; i < queries.size(); i ++){
if(si[queries[i][1]].find(queries[i][0]) == si[queries[i][1]].end())
vb.push_back(false);
else
vb.push_back(true);
}
return vb;
}
};
这个题还是比较难,想了几个小时也没想出来,感觉太复杂了。。只动态规划出了一个机器人的最佳路线,如果是两个机器人同时从上往下摘樱桃的话,在两个机器人路径的交叉点,我认为是需要分类讨论的,这位老哥Ikaruga的dp不错,是把两个机器人的位置信息一起记录下来的。
这里就只放我一个机器人路径的代码吧。
class Solution {
public:
struct point{
point(int a, int b){
this->x = a;
this->y = b;
}
int x,y;
};
struct node{
vector<point> vi; //当前节点获得最大樱桃数的路径
int max_sum; //当前节点获得的最大樱桃数
};
node compare2(node a, node b){
if(a.max_sum > b.max_sum) return a;
return b;
}
int cherryPickup(vector<vector<int>>& grid) {
vector<vector<node>> vvn;
// 第一次动态规划过程
for(int i = 0; i < grid.size(); i ++){
vector<node> vn;
for(int j = 0; j < grid[i].size(); j ++){
node n;
// 边界判定
if(j-i <= 0 || j+i+1 >= grid[i].size()){
// 点在顶部
if(i == 0) {
n.max_sum = grid[i][j];
}
// 点在最左边
else if(j == 0){
node m = compare2(vvn[i-1][j], vvn[i-1][j+1]);
n.max_sum = m.max_sum + grid[i][j];
n.vi = m.vi;
}
// 点在最右边
else if(j + 1 == grid[i].size()){
node m = compare2(vvn[i-1][j], vvn[i-1][j-1]);
n.max_sum = m.max_sum + grid[i][j];
n.vi = m.vi;
}
// 其他情况
else{
node m = compare2(compare2(vvn[i-1][j-1], vvn[i-1][j]), vvn[i-1][j+1]);
n.max_sum = m.max_sum + grid[i][j];
n.vi = m.vi;
}
n.vi.push_back(point(i, j));
}
else{
n.max_sum = 0;
}
cout << n.max_sum << endl;
vn.push_back(n);
}
vvn.push_back(vn);
}
int a = vvn.size()-1;
node n1 = vvn[a][0]; //第一个路径
node n2 = n1;
for(int i = 1; i < vvn[a].size(); i ++){
if(n1.max_sum < vvn[a][i].max_sum){
n2 = n1;
n1= vvn[a][i];
}
}
return n1.max_sum + n2.max_sum;
}
};