文章目录
- 竞赛链接
- Q1:2899. 上一个遍历的整数💩(阅读理解题,按题意模拟)
- Q2:2900. 最长相邻不相等子序列 I(贪心)
- Q3:2901. 最长相邻不相等子序列 II(类似 最长上升子序列,记录具体序列元素)
- 代码1——自己写的
- 代码2——记录from数组
- Q4:2902. 和带限制的子多重集合的数目(多重背包方案数:从朴素 DP 到优化)
- 解法1——朴素的多重背包(超时)
- 解法2——多重背包/分组背包 DP优化(TODO)⭐
- 成绩记录
竞赛链接
https://leetcode.cn/contest/biweekly-contest-115/
Q1:2899. 上一个遍历的整数💩(阅读理解题,按题意模拟)
https://leetcode.cn/problems/last-visited-integers/description/
提示:
1 <= words.length <= 100
words[i] == "prev" 或 1 <= int(words[i]) <= 100
题目有一丢丢难理解,要慢慢看。
用一个nums列表存储已经枚举过的数字,枚举到prev的时候取出放入ans就好了。
class Solution {public List<Integer> lastVisitedIntegers(List<String> words) {List<Integer> ans = new ArrayList<>(), ls = new ArrayList<>();int k = 0;for (String word: words) {if ("prev".equals(word)) {k++;if (k > ls.size()) ans.add(-1);else ans.add(ls.get(ls.size() - k));// 倒数第k个} else {k = 0;// k清零ls.add(Integer.parseInt(word));}}return ans;}
}
Q2:2900. 最长相邻不相等子序列 I(贪心)
https://leetcode.cn/problems/longest-unequal-adjacent-groups-subsequence-i/description/
1 <= n == words.length == groups.length <= 100
1 <= words[i].length <= 10
0 <= groups[i] < 2
words 中的字符串 互不相同 。
words[i] 只包含小写英文字母。
题目要求两个相邻位置的 group 不能相等,没有别的要求,那么只要 group 发生了变化就加入答案即可。
class Solution {public List<String> getWordsInLongestSubsequence(int n, String[] words, int[] groups) {List<String> ans = new ArrayList<>();int last = -1; // 记录上一个group值for (int i = 0; i < n; ++i) {if (groups[i] != last) {last = groups[i];ans.add(words[i]);}}return ans;}
}
Q3:2901. 最长相邻不相等子序列 II(类似 最长上升子序列,记录具体序列元素)
https://leetcode.cn/problems/longest-unequal-adjacent-groups-subsequence-ii/description/
提示:
1 <= n == words.length == groups.length <= 1000
1 <= words[i].length <= 10
1 <= groups[i] <= n
words 中的字符串 互不相同 。
words[i] 只包含小写英文字母。
代码1——自己写的
class Solution {public List<String> getWordsInLongestSubsequence(int n, String[] words, int[] groups) {int[] dp = new int[n];Arrays.fill(dp, 1);int mlId = 0, ml = 0;List<String>[] ans = new ArrayList[n];for (int i = 0; i < n; ++i) {ans[i] = new ArrayList<>();ans[i].add(words[i]);for (int j = 0; j < i; ++j) {if (groups[i] != groups[j] && check(words[i], words[j])) {if (dp[j] + 1 > dp[i]) {dp[i] = dp[j] + 1;ans[i] = new ArrayList<>(ans[j]);;ans[i].add(words[i]);}}}if (dp[i] > ml) {ml = dp[i];mlId = i;}}return ans[mlId];}public boolean check(String a, String b) {if (a.length() != b.length()) return false;boolean f = false;for (int i = 0; i < a.length(); i++) {if (a.charAt(i) != b.charAt(i)) {if (f) return false;f = true;}}return f;}
}
代码2——记录from数组
https://leetcode.cn/problems/longest-unequal-adjacent-groups-subsequence-ii/solutions/2482844/zi-xu-lie-dp-de-si-kao-tao-lu-pythonjava-kmaf/
class Solution {public List<String> getWordsInLongestSubsequence(int n, String[] words, int[] groups) {int[] dp = new int[n], from = new int[n];Arrays.fill(dp, 1);int id = 0;for (int i = 0; i < n; ++i) {from[i] = i;for (int j = 0; j < i; ++j) {if (groups[i] != groups[j] && check(words[i], words[j])) {if (dp[j] + 1 > dp[i]) {dp[i] = dp[j] + 1;from[i] = j;}}}if (dp[i] > dp[id]) id = i;}List<String> ans = new ArrayList<>();int m = dp[id];for (int i = 0; i < m; ++i) {ans.add(words[id]);id = from[id];}Collections.reverse(ans);return ans;}public boolean check(String a, String b) {if (a.length() != b.length()) return false;boolean f = false;for (int i = 0; i < a.length(); i++) {if (a.charAt(i) != b.charAt(i)) {if (f) return false;f = true;}}return f;}
}
还可以倒序求 dp,这样最后列表就不用翻转了。
Q4:2902. 和带限制的子多重集合的数目(多重背包方案数:从朴素 DP 到优化)
https://leetcode.cn/problems/count-of-sub-multisets-with-bounded-sum/description/
提示:
1 <= nums.length <= 2 * 10^4
0 <= nums[i] <= 2 * 10^4
nums 的和不超过 2 * 10^4 。
0 <= l <= r <= 2 * 10^4
解法1——朴素的多重背包(超时)
相当于求 dp[l],…,dp[r] 之和,dp[i] 表示组成 i 的方案数。
将相同数字分到同一组,完成
class Solution {public int countSubMultisets(List<Integer> nums, int l, int r) {Map<Integer, Integer> cnt = new HashMap<>();for (int x: nums) cnt.merge(x, 1, Integer::sum);final long MOD = (int)1e9 + 7;long[] dp = new long[r + 1];dp[0] = 1;for (int x: cnt.keySet()) { // 枚举组if (x == 0) continue;for (int j = r; j >= 0; --j) { // 枚举容量for (int i = 1; i <= cnt.get(x); ++i) { // 枚举组内物品if (j >= x * i) dp[j] = (dp[j] + dp[j - x * i]) % MOD;}}}long ans = 0;for (int i = l; i <= r; ++i) {ans = (ans + dp[i]) % MOD;}return (int)((ans * (cnt.getOrDefault(0, 0) + 1)) % MOD);}
}
解法2——多重背包/分组背包 DP优化(TODO)⭐
成绩记录
本次没有参加竞赛。