问题1: 给你一个整数数组 nums。 在一次操作中,你需要移除当前数组的 前三个元素。如果剩余元...
बनाया गया: 20 दिसंबर 2025
का उपयोग करके उत्तर दिया गया GPT-5.2 Thinking द्वारा Chat01
बनाया गया: 20 दिसंबर 2025
का उपयोग करके उत्तर दिया गया GPT-5.2 Thinking द्वारा Chat01
问题1:
给你一个整数数组 nums。
在一次操作中,你需要移除当前数组的 前三个元素。如果剩余元素少于三个,则移除 所有 剩余元素。
重复此操作,直到数组为空或不包含任何重复元素为止。
返回一个整数,表示所需的操作次数。
示例 1:
输入: nums = [3,8,3,6,5,8]
输出: 1
解释:
在第一次操作中,我们移除前三个元素。剩余的元素 [6, 5, 8] 互不相同,因此停止。仅需要一次操作。
示例 2:
输入: nums = [2,2]
输出: 1
解释:
经过一次操作后,数组变为空,满足停止条件。
示例 3:
输入: nums = [4,3,5,1,2]
输出: 0
解释:
数组中的所有元素都是互不相同的,因此不需要任何操作。
提示:
1 <= nums.length <= 105
1 <= nums[i] <= 105
class Solution {
public int minOperations(int[] nums) {
}
}
问题2:
给你一个整数数组 nums。
你的任务是从 nums 中选择 恰好三个 整数,使得它们的和能被 3 整除。
返回这类三元组可能产生的 最大 和。如果不存在这样的三元组,返回 0。
示例 1:
输入: nums = [4,2,3,1]
输出: 9
解释:
总和能被 3 整除的有效三元组为:
(4, 2, 3),和为 4 + 2 + 3 = 9。
(2, 3, 1),和为 2 + 3 + 1 = 6。
因此,答案是 9。
示例 2:
输入: nums = [2,1,5]
输出: 0
解释:
没有三元组的和能被 3 整除,所以答案是 0。
提示:
3 <= nums.length <= 10^5
1 <= nums[i] <= 10^5
class Solution {
public int maximumSum(int[] nums) {
}
}
问题3:
给你一个长度为 n 的整数数组 nums 和一个相同长度的二进制字符串 s。
一开始,你的分数为 0。对于每一个 s[i] = '1' 的下标 i,都会为分数贡献 nums[i]。
你可以执行 任意 次操作(包括零次)。在一次操作中,你可以选择一个下标 i(0 <= i < n - 1),满足s[i] = '0' 且 s[i + 1] = '1',并交换这两个字符。
返回一个整数,表示你可以获得的 最大可能分数。
示例 1:
输入: nums = [2,1,5,2,3], s = "01010"
输出: 7
解释:
我们可以执行以下交换操作:
在下标 i = 0 处交换:"01010" 变为 "10010"
在下标 i = 2 处交换:"10010" 变为 "10100"
下标 0 和 2 包含 '1',贡献的分数为 nums[0] + nums[2] = 2 + 5 = 7。这是可以获得的最大分数。
示例 2:
输入: nums = [4,7,2,9], s = "0000"
输出: 0
解释:
字符串 s 中没有字符 '1',因此无法执行交换操作。分数保持为 0。
提示:
n == nums.length == s.length
1 <= n <= 10^5
1 <= nums[i] <= 10^9
s[i] 是 '0' 或 '1'
class Solution {
public long maximumScore(int[] nums, String s) {
}
}
问题4:
给你一个整数 n。
我们将 1 到 n 的整数按从左到右的顺序排成一个序列。然后,交替地执行以下两种操作,直到只剩下一个整数为止,从操作 1 开始:
操作 1:从左侧开始,隔一个数删除一个数。
操作 2:从右侧开始,隔一个数删除一个数。
返回最后剩下的那个整数。
示例 1:
输入: n = 8
输出: 3
解释:
写下序列 [1, 2, 3, 4, 5, 6, 7, 8]。
从左侧开始,我们删除每隔一个数字:[1, 2, 3, 4, 5, 6, 7, 8]。剩下的整数是 [1, 3, 5, 7]。
从右侧开始,我们删除每隔一个数字:[1, 3, 5, 7]。剩下的整数是 [3, 7]。
从左侧开始,我们删除每隔一个数字:[3, 7]。剩下的整数是 [3]。
示例 2:
输入: n = 5
输出: 1
解释:
写下序列 [1, 2, 3, 4, 5]。
从左侧开始,我们删除每隔一个数字:[1, 2, 3, 4, 5]。剩下的整数是 [1, 3, 5]。
从右侧开始,我们删除每隔一个数字:[1, 3, 5]。剩下的整数是 [1, 5]。
从左侧开始,我们删除每隔一个数字:[1, 5]。剩下的整数是 [1]。
示例 3:
输入: n = 1
输出: 1
解释:
写下序列 [1]。
最后剩下的整数是 1。
提示:
1 <= n <= 10^15
class Solution {
public long lastInteger(long n) {
}
} 解决这4个问题,通过所有例子,并且不能超时
下面给出 4 题的不超时解法(Java),每题都满足题意与约束。
设删了 次后,数组从下标 开始的后缀保留。我们要找最小 ,使得这个后缀没有重复。
从右往左扫,用 HashSet 维护后缀元素:
i+1)的后缀是全不同的,这就是阈值 t = i+1。ceil(t/3)。javaimport java.util.*; class Solution { public int minOperations(int[] nums) { int n = nums.length; HashSet<Integer> seen = new HashSet<>(); int t = 0; // 最小下标,使得 nums[t..n-1] 全不同 for (int i = n - 1; i >= 0; i--) { if (seen.contains(nums[i])) { t = i + 1; break; } seen.add(nums[i]); } // 需要把前缀至少删到 t,且每次删 3 个 return (t + 2) / 3; // ceil(t/3) } }
复杂度:O(n) 时间,O(n) 空间。
只可能的余数组合(mod 3)使总和 %3==0:
因此只需分别保存每个余数类的前三大,枚举上述 4 种组合取最大即可。
javaimport java.util.*; class Solution { private void addTop3(int[] top, int val) { // top 降序,长度 3 for (int i = 0; i < 3; i++) { if (val > top[i]) { for (int j = 2; j > i; j--) top[j] = top[j - 1]; top[i] = val; return; } } } private int sumNeed(int[] top, int need) { if (need == 0) return 0; if (top[need - 1] == 0) return -1; // 不足 need 个(因为 nums[i] >= 1,0 可当哨兵) int s = 0; for (int i = 0; i < need; i++) s += top[i]; return s; } public int maximumSum(int[] nums) { int[] t0 = new int[3], t1 = new int[3], t2 = new int[3]; for (int x : nums) { int r = x % 3; if (r == 0) addTop3(t0, x); else if (r == 1) addTop3(t1, x); else addTop3(t2, x); } int ans = 0; int s000 = sumNeed(t0, 3); if (s000 != -1) ans = Math.max(ans, s000); int s111 = sumNeed(t1, 3); if (s111 != -1) ans = Math.max(ans, s111); int s222 = sumNeed(t2, 3); if (s222 != -1) ans = Math.max(ans, s222); int a = sumNeed(t0, 1), b = sumNeed(t1, 1), c = sumNeed(t2, 1); if (a != -1 && b != -1 && c != -1) ans = Math.max(ans, a + b + c); return ans; } }
复杂度:O(n) 时间,O(1) 空间。
一次操作让某个 '1' 向左移动一格(跨过一个 '0'),因此:
s[i]=='1',就必须保证最终在 [0..i] 里至少放下这么多个 '1'(因为这些 '1' 不能向右跑出前缀)。贪心做法:
nums[i] 放进大根堆'1',就从堆里取当前前缀能选到的最大值加入答案javaimport java.util.*; class Solution { public long maximumScore(int[] nums, String s) { PriorityQueue<Long> pq = new PriorityQueue<>(Collections.reverseOrder()); long ans = 0L; for (int i = 0; i < nums.length; i++) { pq.offer((long) nums[i]); if (s.charAt(i) == '1') { ans += pq.poll(); // 必须在 [0..i] 里新增一个 '1',取最大收益位置 } } return ans; } }
复杂度:O(n log n) 时间,O(n) 空间。(n=1e5 完全可过)
题目示例表明:从某侧开始时,第一个数保留,删第二个,保留第三个……
例如 n=8,第一次从左删掉 2,4,6,8,留下 1,3,5,7。
用等差数列表示当前剩余序列:
head:当前序列第一个数step:相邻剩余数间距rem:剩余个数left:当前从左还是从右操作更新规则:
head 不变;rem = ceil(rem/2);step *= 2rem 为偶数,保留下标为奇数的元素,head += steprem = ceil(rem/2);step *= 2javaclass Solution { public long lastInteger(long n) { long head = 1; long step = 1; long rem = n; boolean left = true; // 操作1从左开始 while (rem > 1) { if (left) { // 从左:保留第一个,删第二个... // head 不变 } else { // 从右:保留最后一个,删倒数第二个... if ((rem & 1L) == 0L) { head += step; // rem 偶数时,最左边保留下标为 1 的元素 } } rem = (rem + 1) / 2; // ceil(rem/2) step *= 2; left = !left; } return head; } }
复杂度:O(log n) 时间,O(1) 空间。
如果你希望我把 4 题整合成一个文件(用不同类名或不同方法名)方便本地运行,我也可以直接给你一份可复制粘贴的版本。