升序排列的数组nums,原地删除重复出现的元素,使得每个元素只出现一次,返回删除后数组的新长度,要求元素的相对顺序保持一致
时间: 2024-12-11 15:33:55 浏览: 16
当需要在一个升序排列的数组`nums`中删除重复元素,并保持元素的相对顺序不变时,可以使用双指针法。算法的基本步骤如下:
1. 定义两个指针,一个指向数组的起始位置(i),另一个指向当前未处理的位置(j)。初始时,i 和 j 都指向第一个元素。
2. 比较 `nums[i]` 和 `nums[j]`,如果它们相等,将 i 向右移动一位,直到找到不重复的元素或者 `i` 超出数组范围。
3. 如果 `nums[i]` 不等于 `nums[j]`,说明 `nums[i]` 是新的唯一值,将它复制到 `nums[j+1]` 并将 `j` 向右移动一位。
4. 重复步骤 2 和 3,直到 `i` 等于数组的结束位置 `n`。
5. 最终,`j + 1` 就是新数组的长度,因为所有不重复的元素都在 `0` 到 `j` 的范围内。
下面是一个简单的Python示例:
```python
def removeDuplicates(nums):
if not nums:
return 0
n = len(nums)
j = 1 # 新元素的位置
for i in range(1, n):
if nums[i] != nums[i - 1]:
nums[j] = nums[i]
j += 1
return j
```
相关问题
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
### 回答1:
题目描述:
给定一个升序排列的数组 nums,要求原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。元素的相对顺序应该保持一致。
回答:
题目要求我们原地删除重复出现的元素,也就是不能使用额外的空间,只能在原数组上进行操作。我们可以使用双指针的方法来解决这个问题。
定义两个指针 i 和 j,初始时 i 指向数组的第一个元素,j 指向数组的第二个元素。如果 nums[i] == nums[j],说明 j 指向的元素是重复的,我们就将 j 向后移动一位。如果 nums[i] != nums[j],说明 j 指向的元素不是重复的,我们就将 i 向后移动一位,并将 nums[j] 的值赋给 nums[i],然后将 j 向后移动一位。这样,当 j 遍历完整个数组时,i 指向的就是新数组的最后一个元素,新数组的长度就是 i+1。
代码如下:
```
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if (nums.empty()) {
return 0;
}
int i = 0;
for (int j = 1; j < nums.size(); j++) {
if (nums[i] != nums[j]) {
i++;
nums[i] = nums[j];
}
}
return i + 1;
}
};
```
### 回答2:
首先理解题目要求,是给定一个升序排列的数组,让我们在原地删除其中重复的元素,使得每个元素只出现一次,并返回删除后数组的新长度。需要注意的是,要保持原数组中元素的相对顺序不变。
解题思路是双指针法。我们设置两个指针,一个指针i从数组的第二个元素开始遍历,另一个指针j指向第一个元素。开始时,i和j都指向第一个不同的元素,然后遍历数组,如果i和j指向的元素相等,那么i向后移一位。如果i和j指向的元素不相等,就将i指向的元素复制到j+1的位置上,然后j向后移一位。重复这个过程,直到遍历到数组的末尾,这时候数组中的重复元素已经全部删除了。最后返回j+1表示删除重复元素后新数组的长度。
代码如下所示:
```python
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
if not nums:
return 0
j = 0
for i in range(1, len(nums)):
if nums[i] != nums[j]:
j += 1
nums[j] = nums[i]
return j + 1
```
时间复杂度是O(n),空间复杂度是O(1)。这个方法非常简单易懂,而且在LeetCode中也具有很高的通过率。
### 回答3:
题目描述:
本题的目的是要求对一个已经按升序排列的数组进行去重复操作,保证每个元素仅出现一次,并且不会改变其他元素的排序和相对位置,并最终返回去重后的数组长度。
思路分析:
1. 首先考虑最简单的去重复办法:建立一个HashSet集合,然后遍历整个数组,把所有不重复的元素都放入HashSet集合中。每次遍历时,检查当前元素是否在集合中出现过,如果没有出现过,则将其加入集合中;否则,表示重复元素,直接跳过不做任何操作。
2. 但是题目要求不能用额外的空间,那么我们思考一下是否能够原地修改这个数组。由于数组已经是按照升序排列的了,所以,我们只需要维护前后两个指针(i和j),来扫描整个数组,检查是否有重复元素,如果有的话,我们将其删除即可。注意,题目中要求删除的是重复元素,而不是所有出现的元素,因此,在扫描的过程中,我们只需要让指针i记录下找到的不重复元素的位置,然后将其与后面的相同元素覆盖即可。
代码实现:
Java版
public int removeDuplicates(int[] nums) {
int n = nums.length;
if (n == 0) return 0;
int i = 0, j = 0;
while (j < n) {
if (nums[i] == nums[j]) {
j++;
} else {
nums[++i] = nums[j++];
}
}
return i + 1;
}
C++版
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int n = nums.size();
if (n == 0) return 0;
int i = 0, j = 0;
while (j < n) {
if (nums[i] == nums[j]) {
j++;
} else {
nums[++i] = nums[j++];
}
}
return i + 1;
}
};
Python3版
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
n = len(nums)
if n == 0: return 0
i, j = 0, 0
while j < n:
if nums[i] == nums[j]:
j += 1
else:
nums[i+1] = nums[j]
i += 1
j += 1
return i + 1
时间复杂度分析:
该算法的时间复杂度是O(n),其中n为数组的长度。假设数组中有k个重复的元素,那么每个元素最多被比较一次,因此,时间复杂度是O(n)。由于题目中要求原地修改,所以空间复杂度是O(1)。
用c语言定义一个升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
```c
int removeDuplicates(int* nums, int numsSize){
if (numsSize == 0) return 0;
int slow = 0;
for (int fast = 1; fast < numsSize; fast++) {
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
}
return slow + 1;
}
```
解题思路:
使用快慢指针,快指针遍历整个数组,当快指针指向的元素与慢指针指向的元素不同时,将慢指针后移一位,并将快指针指向的元素赋值给慢指针指向的位置。最后返回慢指针的位置加一,即为新数组的长度。由于原数组是升序排列的,因此相同的元素一定是连续的,可以使用快慢指针相遇的方式来进行去重。时间复杂度为$O(n)$,空间复杂度为$O(1)$。
阅读全文