go语言实现给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过: 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。 返回 k 。 判题标准: 系统会用下面的代码来测试你的题解: int[] nums = [...]; // 输入数组 int[] expectedNums = [...]; // 长度正确的期望答案 int k = removeDuplicates(nums); // 调用 assert k == expectedNums.length; for (int i = 0; i < k; i++) { assert nums[i] == expectedNums[i]; } 如果所有断言都通过,那么您的题解将被 通过。 示例 1: 输入:nums = [1,1,2] 输出:2, nums = [1,2,_] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。 示例 2: 输入:nums = [0,0,1,1,1,2,2,3,3,4] 输出:5, nums = [0,1,2,3,4] 解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。
时间: 2025-07-01 11:28:01 浏览: 7
<think>好的,我现在需要解决一个Go语言的问题,题目是要求原地删除非严格递增排列数组中的重复元素,使得每个元素只出现一次,并返回新长度k。同时,前k个元素必须是唯一的,并且保持原来的顺序。首先,我得仔细理解题目要求。
题目给的示例显示,比如输入[1,1,2],处理后前两个元素是1和2,返回长度2。这说明需要原地修改数组,也就是不能使用额外的数组空间,只能在原数组上操作。那如何做到这一点呢?
想到可能用双指针的方法。因为数组已经是非严格递增的,也就是可能有重复的元素相邻。所以可以维护一个慢指针,表示当前唯一元素的位置,快指针遍历数组。当发现快指针指向的元素与慢指针不同时,就将该元素移动到慢指针的下一个位置,然后慢指针前进一步。这样,遍历完成后,慢指针的位置加一就是新长度。
比如例子中的[0,0,1,1,1,2,2,3,3,4],慢指针初始在0,快指针从1开始。当快指针指向0时,和慢指针相同,继续。当快指针到1的时候,发现不同,于是将慢指针+1的位置设为1,然后慢指针移到1。依此类推,直到处理完所有元素,慢指针最后的位置是4,所以长度是5。
需要考虑边界情况,比如数组为空的情况,这时候直接返回0。如果数组只有一个元素,返回1即可。
那具体的实现步骤可能是:
1. 如果数组长度是0,返回0。
2. 初始化慢指针为0。
3. 快指针从1开始遍历数组。
4. 当nums[fast] != nums[slow]时,将slow加1,然后将nums[fast]赋值给nums[slow]。
5. 遍历结束后,返回slow+1。
这样就能保证前k个元素是唯一的,且顺序不变。这个过程的时间复杂度是O(n),空间复杂度是O(1),符合原地修改的要求。
测试一下这个思路是否正确。比如示例1,初始slow=0,fast从1开始。nums[1]=1等于nums[0],所以不处理。fast到2时,nums[2]=2不等于nums[0],所以slow增加到1,将nums[1]设为2。此时数组变为[1,2,2],返回长度2。正确。
示例2的情况,按照步骤处理后,前五个元素会是0,1,2,3,4,返回5。也符合预期。
那代码应该怎么写呢?在Go中,函数参数是切片,需要修改原切片的内容,并返回k。例如:
func removeDuplicates(nums []int) int {
if len(nums) == 0 {
return 0
}
slow := 0
for fast := 1; fast < len(nums); fast++ {
if nums[fast] != nums[slow] {
slow++
nums[slow] = nums[fast]
}
}
return slow +1
}
这样应该可以解决问题。但是需要注意,当数组长度为0时的处理是否正确。另外,对于所有元素都相同的情况,比如nums = [1,1,1],处理后应该返回1,数组的前1个元素是1。代码中slow初始是0,fast从1到2,每次比较都等于nums[slow],所以不会执行if里的操作。最后返回slow+1=1,正确。
这样应该就能满足题目要求了。测试用例应该都通过。比如示例1和示例2,以及空数组,单元素数组,全相同数组的情况。这样代码应该是正确的。</think>在 Go 语言中,可以通过**双指针技巧**高效解决这个问题。以下是分步实现和详细解释:
---
### **问题分析**
- **输入**:非严格递增排列的数组(允许相邻元素相等)
- **要求**:
1. 原地删除重复元素,使每个元素仅出现一次
2. 保持元素的相对顺序
3. 返回唯一元素的个数 `k`,且前 `k` 个元素为唯一元素
---
### **算法思路**
使用**快慢双指针**:
1. **慢指针 `slow`**:标记当前唯一元素的末尾位置
2. **快指针 `fast`**:遍历数组,寻找与 `slow` 不同的元素
**核心逻辑**:
当 `nums[fast] != nums[slow]` 时,将 `nums[fast]` 复制到 `slow+1` 的位置,并移动 `slow`。
---
### **代码实现**
```go
func removeDuplicates(nums []int) int {
if len(nums) == 0 {
return 0
}
slow := 0 // 慢指针初始位置
for fast := 1; fast < len(nums); fast++ {
if nums[fast] != nums[slow] {
slow++
nums[slow] = nums[fast] // 将非重复元素移动到慢指针后
}
}
return slow + 1 // 返回唯一元素的数量
}
```
---
### **逐步解释**
1. **边界处理**:
若数组为空,直接返回 `0`。
2. **初始化指针**:
- `slow` 从索引 `0` 开始(首个元素默认唯一)
- `fast` 从索引 `1` 开始遍历
3. **遍历过程**:
- 当 `nums[fast] != nums[slow]` 时,说明找到新唯一元素:
- 移动 `slow` 到下一个位置
- 将 `nums[fast]` 赋值给 `nums[slow]`,覆盖重复值
4. **返回结果**:
唯一元素的数量为 `slow + 1`(索引从 `0` 开始)
---
### **示例验证**
以输入 `nums = [0,0,1,1,1,2,2,3,3,4]` 为例:
1. `slow = 0`, `fast` 遍历到 `0`(重复,不处理)
2. `fast` 移动到 `1`(值不同),`slow` 增加到 `1`,赋值 `nums[1] = 1`
3. 重复此过程,最终 `slow` 停在 `4`,返回 `5`
4. 修改后的 `nums` 前 5 个元素为 `[0,1,2,3,4]`
---
### **复杂度分析**
- **时间复杂度**:$O(n)$,仅遍历一次数组
- **空间复杂度**:$O(1)$,原地修改,无额外空间使用
---
### **边界测试案例**
1. **空数组**:`[] → 0`
2. **全重复元素**:`[1,1,1] → 1`
3. **单元素数组**:`[5] → 1`
---
通过这种方法,可以高效且简洁地解决问题,满足题目所有要求。
阅读全文
相关推荐


















