问题1: 给你一个整数数组 nums。 在一次操作中,你需要移除当前数组的 前三个元素。如果剩余元...

Erstellt am: 20. Dezember 2025

Beantwortet mit GPT-5.2 Thinking von Chat01

Frage

问题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个问题,通过所有例子,并且不能超时

Gedanke

Solving the problem of removing repeated elements

For Problem 1, the task is to remove the first three elements repeatedly from the array until the remaining part has no duplicates. The goal is to find the minimal number of operations (k) to ensure this. We continue until 3k elements are removed or until the array is empty. I'll implement this efficiently to meet the constraints.

Optimizing the suffix uniqueness check

To solve this, I'll iterate from the end of the array, using frequency counts to check for duplicates. For each starting index, I'll verify if the suffix from the index onwards has all unique elements. Then, by maintaining counts, I can detect when the suffix becomes unique again after removing duplicates. The goal is to minimize k.

Simplifying suffix uniqueness checking

I'll track the uniqueness of each suffix by storing a boolean array (ok[]) while traversing backward. If the number at an index is already in the set, that suffix is not unique, and I mark it as false. The uniqueness check is monotonic—once false, it remains false. We aim to find the first index where the suffix becomes unique.

Finding the minimal index for unique suffix

The idea is that once a duplicate is encountered, the uniqueness becomes false, and it remains false. For each index, I only need to track when the suffix becomes unique. If suffix starting from some index t is unique, then all indices greater than or equal to t are also unique. The minimal k operations required will be the ceiling of t / 3.

Final Refinement on determining threshold for unique suffix

By scanning from the end, I'll track duplicates to find the smallest index t where the suffix from t is unique. For example, in a list like [3, 8, 3, 6, 5, 8], the first unique suffix starts at index 2. From there, I can calculate the necessary number of operations by finding the smallest multiple of 3 that covers the required elements.

Scanning to find the threshold and maximize sum divisible by 3

We can find the threshold by scanning from the end, using a HashSet. When a duplicate is found, the threshold t is set to i+1. If no duplicate is found, t = 0. The minimum number of operations required is ceil(t / 3). For the second problem, to maximize a sum divisible by 3, we classify numbers by their remainder when divided by 3 and pick the largest values from each group.

Considering remainder cases and binary string sorting

There are four remainder combinations satisfying the sum mod 3 == 0: (0,0,0), (1,1,1), (2,2,2), and (0,1,2). For each case, we’ll compute the sum of the largest available numbers in their respective groups. The solution requires maintaining the top three values in each class, either using a min-heap or sorted array. For the third problem, swapping "01" moves '1's leftward while ensuring their relative order is preserved. This is akin to sorting the binary string in descending order. Swapping always reduces inversion count.

Evaluating binary string configuration with left moves

When moving the ones in a binary string left, the key is making sure that the relative order stays the same. Because ones can only move left past zeros and never right, the challenge is to maximize the sum of the numbers in the positions where the ones end up, adhering to specific constraints about their positions. The final configuration's prefix count of ones cannot exceed the original count, but can increase if ones move into new positions from the right.

Choosing optimal positions for ones with constraints

The idea is to move ones left as far as possible, but they can't pass certain limits, creating a set of constraints. Essentially, I'm picking positions for the ones while ensuring their final positions respect certain rules. By keeping track of previous ones, I can choose where to place new ones to maximize the sum. It's a dynamic process—scanning from left to right, adjusting choices along the way based on how many ones I've seen.

Understanding the movement of ones and zeros

Ones from beyond certain indices can move into previous positions, as long as they respect certain constraints. Essentially, after all the swaps, the binary string will be the result of allowed movements, where zeros and ones retain their relative order. This can be seen as a "shuffle," which helps define possible configurations, respecting the rules of movement for both ones and zeros.

Maximizing sum by placing ones under constraints

To maximize the sum of numbers at selected positions, I need to pick positions for ones such that the final placement respects certain constraints. Specifically, for each index, the number of selected positions up to that point must be at least the number of ones originally there. The challenge is determining where and how to place them.

Optimizing position selection with deadlines

To maximize the sum while selecting specific positions, we need to consider each original '1' as a deadline up to its position. Using a greedy approach, I maintain a heap of candidate positions weighted by their values. Every time we hit a original '1', we commit to choosing positions while respecting the deadlines imposed by those earlier '1's.

Maximizing sum with hierarchical prefix constraints

The problem has nested constraints, where for each original '1', the number of elements chosen up to that point must increase. To solve this, I can use a greedy approach with min-heaps to maintain the best subset of positions that satisfies these constraints. Essentially, this is like managing quotas for nested segments, aiming to maximize the sum of chosen positions.

Maximizing weight with nested deadlines

To solve this problem, it’s essentially about selecting k distinct positions to maximize the sum, ensuring each chosen position meets its nested deadline. By scanning from right to left and choosing the best available position within each range, we can use a max-heap to make a greedy choice while respecting the constraints. The challenge comes with managing the ordering between the selections.

Greedy approach for maximizing sums with deadlines

I’m considering ways to maximize the sum of values under the constraint that selected positions must follow a specific order. A left-to-right process is appealing, where each deadline is met by picking the best available position within the allowed range. It seems that aiming for the highest values as the deadlines trigger might yield an optimal solution since choosing the best values early won't block later selections, as long as indices remain distinct.

Optimizing selection for sum maximization

I’m thinking about the challenge of maintaining a fixed selection while optimizing the sum. At each step, I will pick the highest available values within the required prefix, ensuring that the earlier selections don’t conflict with future ones. Adding values carefully ensures we're maximizing total sum while respecting deadlines.

Greedy algorithm for optimal selection

I’m considering a greedy approach where I always pick the best available value within the current prefix, given the requirements at each step. I’ve tested a few cases, and this method seems to work well for the constraints. Ensuring values are chosen without violating future selection conditions looks feasible.

Proving the greedy algorithm's correctness

The algorithm works by always selecting the best possible value within each prefix, ensuring optimal picks for each step. By maintaining a max-heap and popping the largest available value at each required position, it guarantees the best possible selections under given constraints. This approach matches optimality criteria necessary for this type of problem.

Final solution for multiple problems

I’m tackling multiple problems in sequence — each with distinct approaches. For the first problem, I’m using a HashSet to track duplicates from the right, ensuring unique suffixes. The second problem involves managing arrays and counts for top values, where I’ll track the necessary sums efficiently. Each scenario has its own solution, keeping complexities manageable. We’ll just need clear explanation and minimal code.

Clarifying elimination game logic

The problem involves an elimination game that differs from the standard approach. It’s about removing every second number starting with the second one, rather than deleting from the front. So, after each round, you have to adjust the “head” and “step” rules accordingly, keeping the first element each time but modifying the step based on whether you’re working from the left or right. My understanding of the problem should now be aligned.

Thought for 4m 35s

Antwort

下面给出 4 题的不超时解法(Java),每题都满足题意与约束。


问题1:每次删前三个,直到为空或无重复

思路

设删了 kk 次后,数组从下标 3k3k 开始的后缀保留。我们要找最小 kk,使得这个后缀没有重复

从右往左扫,用 HashSet 维护后缀元素:

  • 一旦遇到“当前值已在 set 中”,说明从这个位置开始后缀出现重复;
  • 但从它的下一位开始(即 i+1)的后缀是全不同的,这就是阈值 t = i+1
  • 答案就是最小的 3 的倍数删到 ≥t:ceil(t/3)

代码

java
import 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) 空间。


问题2:恰好选 3 个数,和能被 3 整除,最大和

思路

只可能的余数组合(mod 3)使总和 %3==0:

  • (0,0,0)
  • (1,1,1)
  • (2,2,2)
  • (0,1,2)

因此只需分别保存每个余数类的前三大,枚举上述 4 种组合取最大即可。

代码

java
import 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) 空间。


问题3:交换 "01"->"10",最大化 '1' 位置的 nums 和

关键结论

一次操作让某个 '1' 向左移动一格(跨过一个 '0'),因此:

  • 扫到第 i 位时,如果 s[i]=='1',就必须保证最终在 [0..i] 里至少放下这么多个 '1'(因为这些 '1' 不能向右跑出前缀)。

贪心做法:

  • 从左到右,把每个 nums[i] 放进大根堆
  • 每遇到一个 '1',就从堆里取当前前缀能选到的最大值加入答案
    这样保证每个前缀的“必须选满的数量”都拿到最大收益。

代码

java
import 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 完全可过)


问题4:1..n 交替从左/右“隔一个删一个”,返回最后剩下的数(n 到 1e15)

注意(和经典题的区别)

题目示例表明:从某侧开始时,第一个数保留,删第二个,保留第三个……
例如 n=8,第一次从左删掉 2,4,6,8,留下 1,3,5,7。

用等差数列表示当前剩余序列:

  • head:当前序列第一个数
  • step:相邻剩余数间距
  • rem:剩余个数
  • left:当前从左还是从右操作

更新规则:

  • 从左(保留第一个):head 不变;rem = ceil(rem/2)step *= 2
  • 从右(保留最后一个):
    • rem 为偶数,保留下标为奇数的元素,head += step
    • rem = ceil(rem/2)step *= 2

代码

java
class 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 题整合成一个文件(用不同类名或不同方法名)方便本地运行,我也可以直接给你一份可复制粘贴的版本。

Diesen Q&A teilen