LeetCode(Weekly Contest 188)题解
作者:互联网
0. 前言
- 中文版地址:https://leetcode-cn.com/contest/weekly-contest-188/
- 英文版地址:https://leetcode.com/contest/weekly-contest-188/
1. 题解
1.1 5404. 用栈操作构建数组(1441. Build an Array With Stack Operations)
- 中文版题目描述:https://leetcode-cn.com/problems/build-an-array-with-stack-operations/
- 英文版题目描述:https://leetcode.com/problems/build-an-array-with-stack-operations/
- 思路:模拟
- 遍历 1 到 n
- 如果和 target 当前值相等则答案追加一个 "Push",当前位置 +1;否则答案追加一个 "Push" 和 "Pop"
- 代码如下:
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)
- 中文版题目描述:https://leetcode-cn.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/
- 英文版题目描述:https://leetcode.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/
- 思路:暴力 or 哈希统计,暴力法即枚举两个区间端点,下面讲一下哈希法
- 如果 a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1],b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k], a = b
- 则 a ^ b = 0,且 arr[i,...,k] 内任意两端相邻区间异或和均相等,则 arr[i,...,k] 会贡献 k-i 个答案
- 用哈系数组,记录每个前缀哈希和的各个位置
- 暴力代码如下:
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)
- 中文版题目描述:https://leetcode-cn.com/problems/minimum-time-to-collect-all-apples-in-a-tree/
- 英文版题目描述:https://leetcode.com/problems/minimum-time-to-collect-all-apples-in-a-tree/
- 思路:递归 or 某大神的 七行代码 解法
- 递归遍历两次,首先遍历所有节点判断是否需要走,叶子节点没有苹果,则没必要走
- 如果子节点有一个必须要走,父亲节点也要走
- 然后第二次递归计算路径长度,父亲节点往返子节点路径要 +2
- 七行代码,默认边的左节点都是递增的,更新必要节点和计算边就免去了递归,Or2
- 递归代码如下:
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. 参考文献
- https://leetcode-cn.com/problems/count-triplets-that-can-form-two-arrays-of-equal-xor/solution/qian-zhui-yi-huo-he-ha-xi-biao-xiang-jie-by-wangdh/
- https://leetcode-cn.com/problems/minimum-time-to-collect-all-apples-in-a-tree/solution/biao-ji-qi-xing-dai-ma-by-lawskivsky/
- https://leetcode-cn.com/problems/number-of-ways-of-cutting-a-pizza/solution/dong-tai-gui-hua-c-by-smilyt_/
标签:arr,Contest,int,题解,vector,https,188,com,dp 来源: https://www.cnblogs.com/wangao1236/p/12863965.html