补:leetcode第 27 场双周赛,1460、1461、1462

补:leetcode第 27 场双周赛,1460、1461、1462

1460. 通过翻转子数组使两个数组相等

第一感觉,只要所有的数字相同,就可以翻转得到。证明略。。。

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;
    }
};

1461. 检查一个字符串是否包含所有长度为 K 的二进制子串

把字符串中长度为k的子串,全部转换成十进制数字,然后看这些数字是否是 0 , 1 , 2 , . . . , 2 k − 1 0,1,2,...,2^k-1 0,1,2,...,2k1
看了别人的题解,直接比较不同的长度为 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;
    }
};

1462. 课程安排 IV

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;

    }
};

1463. 摘樱桃 II

这个题还是比较难,想了几个小时也没想出来,感觉太复杂了。。只动态规划出了一个机器人的最佳路线,如果是两个机器人同时从上往下摘樱桃的话,在两个机器人路径的交叉点,我认为是需要分类讨论的,这位老哥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;
        
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值