0. 前言
- 中文版地址:https://leetcode-cn.com/contest/weekly-contest-183/
- 英文版地址:https://leetcode.com/contest/weekly-contest-183/
1. 题解
1.1 5376. 非递增顺序的最小子序列(1403. Minimum Subsequence in Non-Increasing Order)
- 中文版题目描述:https://leetcode-cn.com/problems/minimum-subsequence-in-non-increasing-order/
- 英文版题目描述:https://leetcode.com/problems/minimum-subsequence-in-non-increasing-order/
- 思路:签到题,降序排序,当前和超过总和一半时退出循环
- 代码如下:
class Solution { public: vector<int> minSubsequence(vector<int>& nums) { sort(nums.begin(), nums.end(), [](int x, int y) { return x > y; }); int sum = 0; for (auto v : nums) { sum += v; } int cur = 0; vector<int> res; for (auto v : nums) { if (cur * 2 > sum) break; cur += v; res.push_back(v); } return res; } };
1.2 5377. 将二进制表示减到 1 的步骤数(1404. Number of Steps to Reduce a Number in Binary Representation to One)
- 中文版题目描述:https://leetcode-cn.com/problems/number-of-steps-to-reduce-a-number-in-binary-representation-to-one/
- 英文版题目描述:https://leetcode.com/problems/number-of-steps-to-reduce-a-number-in-binary-representation-to-one/
- 思路:找规律:
- 末尾为 0,结果即加上末尾连续 0 的个数
- 末尾为 1,结果首先加 1,表示进位,然后结果加上进位后 0 的个数,此时 0 的个数与进位前,末尾连续 1 的个数相同,同时要把末尾连续 1 之后的第一个 0,变成 1
- 此外,本题模拟也可以实现
- 代码如下:
class Solution { public: int numSteps(string s) { int ans = 0, len = s.length(), cur = len-1; for (int i = len-1 ; i >= 1 ; ) { cout << i << endl; while (cur >= 0 && s[cur] == s[i]) cur--; ans += i-cur; if (s[i] == ‘1‘) { ans++; if (cur >= 0) s[cur] = ‘1‘; } i = cur; } return ans; } };
1.3 5195. 最长快乐字符串(1405. Longest Happy String)
- 中文版题目描述:https://leetcode-cn.com/problems/longest-happy-string/
- 英文版题目描述:https://leetcode.com/problems/longest-happy-string/
- 思路:每次尽可能消耗个数最多的字符,如果和已构造的末尾不同,则消耗两个,否则选择次大的消耗一个
- 第一次做没有用 map 结构保持个数的自动排序,选择所有情况特殊判断,代码长到怀疑人生,虽然过了
- 结束后重新思考了一下,用一个关键词升序的 map 维护字符数量的排序关系
- 代码如下:
class Solution { public: string longestDiverseString(int a, int b, int c) { map<int, vector<char>, greater<int>> mp; if (a > 0) mp[a].push_back(‘a‘); if (b > 0) mp[b].push_back(‘b‘); if (c > 0) mp[c].push_back(‘c‘); int last = a + b + c; string ans = ""; char tail = ‘ ‘; int num = 0; while (last) { bool find = false; for (auto i = mp.begin() ; i != mp.end() ; i++) { int cnt = i->first; if (i == mp.begin()) { for (auto j = i->second.begin() ; j != i->second.end() ; j++) { char cur = *j; if (tail != cur) { if (cnt >= 2) { ans += cur; ans += cur; cnt -= 2; last -= 2; } else { ans += cur; cnt -= 1; last -= 1; } i->second.erase(j); if (i->second.size() == 0) { mp.erase(i); } if (cnt > 0) { mp[cnt].push_back(cur); } find = true; tail = cur; break; } } } else { for (auto j = i->second.begin() ; j != i->second.end() ; j++) { char cur = *j; if (tail != cur) { if (cnt >= 1) { ans += cur; cnt -= 1; last -= 1; } i->second.erase(j); if (i->second.size() == 0) { mp.erase(i); } if (cnt > 0) { mp[cnt].push_back(cur); } find = true; tail = cur; break; } } } if (find) break; } if (!find) break; } return ans; } };
1.4 5379. 石子游戏 III(1406. Stone Game III)
- 中文版题目描述:https://leetcode-cn.com/problems/stone-game-iii/
- 英文版题目描述:https://leetcode.com/problems/stone-game-iii/
- 思路:本题属于信息透明的平等博弈,是博弈论中最基础的一种,思路就是倒着从游戏的最后一步开始反着算,对每个状态计算“玩家从该状态开始能不能获胜/最多能拿多少分”,用类似动态规划的思想一直算到第一步
- dp[i] 表示第 i 到 n-1 堆石子,先手取,能获得的最大值
- 从后往前计算,dp[n] = 0
- dp[i] = max(sum-dp[i+1], sum-dp[i+2], sum-dp[i+3]),其中 sum 表示第 i 到 n-1 堆石子的分数之和
- 代码如下:
class Solution { public: string stoneGameIII(vector<int>& stoneValue) { int n = stoneValue.size(); vector<int> dp = vector<int>(n+1, INT_MIN); dp[n] = 0; int sum = 0; for (int i = n-1 ; i >= 0 ; i--) { sum += stoneValue[i]; for (int j = 1 ; j <= 3 && i+j <= n ; j++) { dp[i] = max(dp[i], sum-dp[i+j]); } } int alice = dp[0], bob = sum-dp[0]; cout << alice << endl; cout << bob << endl; if (alice > bob) return "Alice"; else if (alice < bob) return "Bob"; else return "Tie"; } };
2. 参考文献
原文地址:https://www.cnblogs.com/wangao1236/p/12636784.html
时间: 2024-09-30 10:51:04