[leetcode] 452周赛

bfs找糖果

class Solution {
public:
    int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
        int ans = 0;
        queue<int> q; // 可以使用的箱子
        unordered_set<int> wait; // 有箱子, 但暂时没钥匙
        for (auto b: initialBoxes) {
            if (status[b] == 1) {
                q.push(b);
            } else {
                wait.insert(b);
            }
        }
        unordered_set<int> ks;
        while (!q.empty()) {
            int box = q.front();
            q.pop();
            for (auto k: keys[box]) {
                auto it = wait.find(k);
                if (it != wait.end()) { // 先遇到了箱子, 后拿到的钥匙
                    q.push(*it);
                    wait.erase(it);
                }
                ks.insert(k);
            }
            ans += candies[box];
            for (auto b: containedBoxes[box]) {
                if (status[b] == 1 || ks.find(b) != ks.end()) { // 先拿到了钥匙, 后遇到了箱子
                    q.push(b);
                } else {
                    wait.insert(b);
                }
            }
        }
        return ans;
    }
};

最短路径bfs

short dx[4] = {-1, 0, 1, 0};
short dy[4] = {0,  1, 0,-1};
int vis[20][20][51][1025] = {0}; 
class Solution {
public:
    struct pass{
        int x, y, energy = 0, mask = 0;  
    };
    int minMoves(vector<string>& cl, int energy) {
        
        int n = cl.size(), m = cl[0].size(), x = -1, y = -1; 
        int index[21][21];  
        int cnt = 0;  
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++){
                index[i][j] = -1;  
                if(cl[i][j] == 'S'){
                    x = i;  y = j;
                }
                if(cl[i][j] == 'L')
                    index[i][j] = cnt++; 
            }
        queue<pass> que;
        que.push({x, y, energy, (1 << cnt) - 1});
        while(que.size()){
            auto [tx, ty, en, mask] = que.front();
            if(mask == 0) return vis[tx][ty][en][mask];
            que.pop();
            if(en < 1) continue;
            for (int i = 0; i < 4; i++){
                int nx = tx + dx[i], ny = ty + dy[i];
                if(nx < 0 || nx >= n || ny < 0 || ny >= m || cl[nx][ny] == 'X') continue;
                int ne = en - 1, nm = mask;
                if(cl[nx][ny] == 'R')
                    ne = energy; 
                if(index[nx][ny] != -1){ 
                    nm = mask & ~(1 << index[nx][ny]);
                }
                if(vis[nx][ny][ne][nm]) 
                    continue;
                vis[nx][ny][ne][nm] = vis[tx][ty][en][mask] + 1;
                que.push({nx, ny, ne, nm});
            }
        }
        return -1;
    }
};

子矩阵枚举方法

class Solution {
public:
    vector<vector<int>> minAbsDiff(vector<vector<int>>& grid, int k) {
        int m = grid.size(), n = grid[0].size();
        vector<vector<int>> ret(m - k + 1, vector<int>(n - k + 1, 0));
        for (int i = 0; i <= m - k; ++i) 
        {
            for (int j = 0; j <= n - k; ++j) 
            {
                set<int> s;
                // 收集子矩阵所有元素

                for (int x = i; x < i + k; ++x) {
                    for (int y = j; y < j + k; ++y) {
                        s.insert(grid[x][y]);

                    }
                }
                // 最小绝对差
                //利用set的去重和有序性
                if (s.size() == 1) {
                    ret[i][j] = 0;  //鲁棒性
                } else {
                    int minDiff = INT_MAX;
                    int prev = -1e9;
                    for (int v : s) 
                    {
                        if (prev != -1e9) {
            minDiff = min(minDiff, abs(v - prev));
                        }
                        prev = v;

                    }
                    ret[i][j] = minDiff;
                }
            }
        }
        return ret;
    }
};

划分等积子集

周赛错误思路

class Solution {
public:
    bool checkEqualPartitions(vector<int>& nums, long long target) {
        unsigned long long s = 1; 
        for(int i : nums) s *= i;  
        return s == (unsigned long long) target * target;
    }
};

错误原因

nums = [1,2,8] target = 4

应该是false,按照错误贪心却会判为true


正解dfs:

作为参数枚举的好处:不用手动回溯了

class Solution {
public:
    bool checkEqualPartitions(vector<int>& nums, long long target)

{
        int n = nums.size();
        auto dfs = [&](auto& dfs, int i, long long cur1, long long cur2)

-> bool {
            if (cur1 == target && cur2 == target && i == n) {
                return true;
            }

            if (cur1 > target || cur2 > target) {
                return false;
            }
            if (i == n) {
                return false;
            }


          bool flag = false;
flag = dfs(..., cur1 * nums[i], cur2); //先枚举第一个分支
if (!flag)   flag = dfs(..., cur1, cur2 * nums[i]);//枚举第二个分支


return flag;
        };
       
        return dfs(dfs, 0, 1, 1);
    }
};

设置全局传参

class NumArray {
private:
    vector<int> prefix;
public:
    NumArray(vector<int>& nums) {
        int n=nums.size();
        prefix.resize(n+1,0);
        for(int i=1;i<=n;++i) prefix[i]=prefix[i-1]+nums[i-1];
    }
    
    int sumRange(int left, int right) {
        return prefix[right+1]-prefix[left];
    }
};

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray* obj = new NumArray(nums);
 * int param_1 = obj->sumRange(left,right);
 */

 

构造 平衡二叉树

class Solution {
public:
    /* 在左闭右开区间[left, right),构造二叉树 */
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        
        if (left >= right) return NULL;
        /* 求取分割点下标:midValueIndex */
        int midValueIndex = left + (right-left)/2;// 赋值很巧妙可以更新 新数组的起点
        /* 更新节点值 */
        TreeNode* root = new TreeNode(nums[midValueIndex]);
        /* 左闭右开:[left, midValueIndex) */
        root->left = traversal(nums, left, midValueIndex);
        /* 左闭右开:[midValueIndex + 1, right)*/
        root->right = traversal(nums, midValueIndex + 1, right);
        return root;
    }
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if(nums.size() == 0) return NULL;
        return traversal(nums, 0, nums.size());
    }
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值