• LeetCode(Weekly Contest 188)题解


    0. 前言

    1. 题解

    1.1 5404. 用栈操作构建数组(1441. Build an Array With Stack Operations)

    class Solution {
    public:
        vector<string> buildArray(vector<int>& target, int n) {
            int cur = 0, cnt = target.size();
            vector<string> ans;
            for (int i = 1 ; i <= n ; i++) {
                if (cur == cnt)   break;
                if (target[cur] == i) {
                    ans.push_back("Push");
                    cur++;
                } else {
                    ans.push_back("Push");
                    ans.push_back("Pop");
                }
            }
            return ans;
        }
    };

    1.2 5405. 形成两个异或相等数组的三元组数目(1442. Count Triplets That Can Form Two Arrays of Equal XOR)

    class Solution {
    public:
        int countTriplets(vector<int>& arr) {
            int n = arr.size();
            vector<int> xors = vector<int>(n+1, 0);
            xors[1] = arr[0];
            for (int i = 2 ; i <= n ; i++) {
                xors[i] = arr[i-1] ^ xors[i-1];
            }
            int ans = 0;
            for (int i = 0 ; i < n ; i++) {
                for (int j = i+1 ; j < n ; j++) {
                    for (int k = j ; k < n ; k++) {
                        if (xors[j] ^ xors[i] == xors[k+1] ^ xors[j]) {
                            ans++;
                        }
                    }
                }
            }
            return ans;
        }
    };
    • 哈希代码如下:
    class Solution {
    public:
        int countTriplets(vector<int>& arr) {
            int n = arr.size();
            unordered_map<int, vector<int>> cnt;
            int x = 0, ans = 0;
            cnt[0] = vector<int>();
            cnt[0].push_back(0);
            for (int i = 1 ; i <= n ; i++) {
                x ^= arr[i-1];
                if (cnt.find(x) == cnt.end()) {
                    cnt[x] = vector<int>();
                }
                for (auto j : cnt[x]) {
                    // cout << j+1 << "->" << i << endl;
                    ans += (i - j - 1);
                }
                cnt[x].push_back(i);
            }
            return ans;
        }
    };

    1.3 5406. 收集树上所有苹果的最少时间(1443. Minimum Time to Collect All Apples in a Tree)

    class Solution {
    public:
        bool dfs1(int cur, vector<vector<int>>& adj, vector<bool>& hasApple, vector<bool>& need) {
            need[cur] = hasApple[cur];
            if (0 == (int)adj[cur].size()) {
                return need[cur];
            }
            for (auto next : adj[cur]) {
                if (dfs1(next, adj, hasApple, need)) {
                    need[cur] = true;
                }
            }
            return need[cur];
        }
        int dfs2(int cur, vector<vector<int>>& adj, vector<bool>& need, vector<int>& dp) {
            if (0 == (int)adj[cur].size()) {
                return 0;
            }
            cout << cur << endl;
            if (dp[cur])    return dp[cur];
            for (auto next : adj[cur]) {
                if (!need[next])    continue;
                // cout << cur << "->" << next << endl;
                dp[cur] += 2 + dfs2(next, adj, need, dp);
                // cout << "dp[" << cur << "] = " << dp[cur] << endl;
            }
            return dp[cur];
        }
        int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
            vector<int> dp = vector<int>(n, 0);
            vector<bool> need = vector<bool>(n, false);
            vector<vector<int>> adj = vector<vector<int>>(n, vector<int>());
            for (auto v : edges) {
                adj[v[0]].push_back(v[1]); 
            }
            dfs1(0, adj, hasApple, need);
            dfs2(0, adj, need, dp);
            return dp[0];
        }
    };
    • 七行代码方法如下:
    class Solution {
    public:
        int minTime(int n, vector<vector<int>>& edges, vector<bool>& hasApple) {
            for (int i = (int)edges.size()-1 ; i >= 0 ; i--) {
                if (hasApple[edges[i][1]] == true) {
                    hasApple[edges[i][0]] = true;
                }
            }
            int ans = 0;
            for (int i = (int)edges.size()-1 ; i >= 0 ; i--) {
                if (hasApple[edges[i][1]]) ans += 2;
            }
            return ans;
        }
    };

    1.4 5407. 切披萨的方案数(1444. Number of Ways of Cutting a Pizza)

    • 中文版题目描述:https://leetcode-cn.com/problems/number-of-ways-of-cutting-a-pizza/
    • 英文版题目描述:https://leetcode.com/problems/number-of-ways-of-cutting-a-pizza/
    • 思路:dp,dp[i][j][k] 表示切了 k-1 刀,剩余披萨左上角第 i 行 j 列为左上角的切法数量,初始化 dp[1][1][1] = 1
      • 二层遍历剩余左上角,然后逐行判断是否可以切,在更新以切口处为左上角的披萨,切了 k 刀的切法,然后再逐列切,方法同上,复杂度为 O(N^4)
      • 判断切口两端是否 'A',可以通过容斥原理计算,nums[i][j] 表示以第 i 行 j 列为右下角,第 1 行 1 列为左上角的 'A' 大数量
    • 二分法代码如下:
    class Solution {
    public:
        int numA(int r, int c, vector<vector<int>>& nums, int ru, int cu) {
            // cout << "numA:" << ru << " " << cu << " " << r << " " << c << endl;
            // cout << nums[r][c] << "-" << nums[ru-1][c] << "-" << nums[r][cu-1] << "-" << nums[ru-1][cu-1] << endl;
            return nums[r][c] - (nums[ru-1][c] + nums[r][cu-1] - nums[ru-1][cu-1]);
        }
        int ways(vector<string>& pizza, int k) {
            int  r = (int)pizza.size(), c = (int)pizza[0].length(), mod = 1000000007;
            vector<vector<int>> nums = vector<vector<int>>(r+1, vector<int>(c+1, 0));
            for (int i = 1 ; i <= r ; i++) {
                for (int j = 1 ; j <= c ; j++) {
                    nums[i][j] = nums[i-1][j] + nums[i][j-1] - nums[i-1][j-1] + (int)(pizza[i-1][j-1] == 'A');
                }
            }
            vector<vector<vector<int>>> dp = vector<vector<vector<int>>>(r+1, vector<vector<int>>(c+1, vector<int>(k+1)));
            dp[1][1][1] = 1;
            for (int cut = 2 ; cut <= k ; cut++) {
                for (int i = 1 ; i <= r ; i++) {
                    for (int j = 1 ; j <= c ; j++) {
                        if (dp[i][j][cut-1] == 0) continue;
                        int cntIJ = numA(r, c, nums, i , j);
                        for (int l = i ; l < r ; l++) {
                            int cntLJ = numA(r, c, nums, l+1, j);
                            if (cntIJ - cntLJ > 0 && cntLJ > 0) {
                                dp[l+1][j][cut] +=  dp[i][j][cut-1];
                                dp[l+1][j][cut] %= mod;
                            }
                        }
                        for (int l = j ; l < c ; l++) {
                            int cntIL = numA(r, c, nums, i, l+1);
                            if (cntIJ - cntIL > 0 && cntIL > 0) {
                                dp[i][l+1][cut] += dp[i][j][cut-1];
                                dp[i][l+1][cut] %= mod;
                            }
                        }
                    }
                }
            }
    
            int ans = 0;
            for (int i = 1 ; i <= r ; i++) {
                for (int j = 1 ; j <= c ; j++) {
                    ans += dp[i][j][k];
                    ans %= mod;
                }
            }
            return ans;
        }
    };

    3. 参考文献 

  • 相关阅读:
    TPS限流
    JDK并发基础与部分源码解读
    tomcat6-servlet规范对接 与 ClassLoader隔离
    tomcat6-输入输出buffer设计
    tomcat6-endpoint设计
    springMVC请求路径 与实际资源路径关系
    mysql 常用的数据类型
    认识IPv4分组
    CSMA/CD协议(载波侦听多路访问/碰撞检测) 最小帧长理解
    简单的vector--- 2
  • 原文地址:https://www.cnblogs.com/wangao1236/p/12863965.html
Copyright © 2020-2023  润新知