LeetCode/删除有序数组中的重复项
给你一个升序排列的数组 nums ,请你原地删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的相对顺序应该保持一致 。
1. 暴力法
从前往后或者从后往前遍历,碰到相同元素,则把后面所有元素前移,覆盖掉该相同元素,时间复杂度为O(n2)
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int n =nums.size();
for(int i=n-1;i>0;i--){//从后往前
if(nums[i-1]==nums[i]){
for(int j = i-1;j<n-1;j++)//注意j的遍历范围,不要使得j+1溢出
nums[j] = nums[j+1];
n--;
}
}
return n;
}
};
2. 双指针映射
记录一个无重复数组指针位置,记录一个遍历全数组指针,做无重复元素数组到全数组的映射
本质上也是无重复数组的不断扩大
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int n =nums.size();
//两个指针做映射
int k = 1;//无重复数组的待插入位置
for(int i=0;i < n-1;i++){//从前往后
if(nums[i]==nums[i+1]) continue;//这里可以直接判断相邻两个数,也可以与无重复数组最后一个数比较,都是等价的
nums[k] = nums[i+1];//nums[i+1]是第一个不重复的数
k++;
}
return k;
}
};
3. 每个元素可以出现m次
本质上还是已修正数组的扩大,考虑将指针对应数字加入时,判断已修正数组中是否已有m次数,由于是有序的,直接取对应索引值判断即可
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int n =nums.size();
m = 2;//这里以两次为例
int k = 0;//已修正数组的待插入位置
for(int i=0;i < n;i++)//从前往后
if(i<m||nums[k-m]!=nums[i])//先填充小于2的值,然后判断修正数组中,是否有两个相同值,没有则插入
nums[k++] = nums[i];
return k;
}
};