26. 删除有序数组中的重复项:给你一个 非严格递增排列 的数组 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];
}
如果所有断言都通过,那么您的题解将被 通过
思路:
- 从题目和单元测试来看
assert nums[i] == expectedNums[i];这部分代码来看,我们不仅仅需要返回去重后的数组长度,还需要将 原数组 中不重复的值,挪动到前K长度内,且题中说明nums的其余元素与nums的大小不重要 - 我想到的是两个思路:
- 将一个篮子内的鸡蛋,放到另一个鸡蛋中,放的过程中移除掉相同的鸡蛋
- 将原本篮子内的鸡蛋按要求重新排序,将后面未重复的挪动到前面
方法一
- 定义新的数组,用来放置未重复的值
- 更新原数组,并返回新数组长度
注意:更新原数组时,我一开始使用的是nums = [...resultArr],但结果就是并没有更新原数组,这里是因为刚开始我将nums数组当作函数removeDuplicates(nums)的参数传递时,传递的是数组nums的指针引用,使用nums = [...resultArr]重新赋值后,函数内部的nums的引用指针已经不是指在原数组上了,而是移动到新的数组[...resultArr]上,所以将不会改动原nums数组。而我们要做的就是直接修改函数内部的nums数组,此时函数内外的数组指向的都是同一个数组对象的引用,内外数组将同步修改结果,因为本就指向同一个数组对象
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
let resultArr = []
let newNums = [...nums]
newNums.forEach((item, index) => {
if (resultArr.indexOf(item) < 0) {
resultArr.push(item)
}
})
// nums = [...resultArr]
nums.splice(0, nums.length)
resultArr.forEach(item => nums.push(item));
console.log('nums', nums)
return resultArr.length
};
方法二
思路:
- 由于是 非严格递增排列 的数组,且
nums的其余元素与nums的大小不重要,所以即使题目中声明元素的 相对顺序 应该保持 一致 ,我们仍然可以使用双指针的形式,来替换达到后元素前移的目的 - 首先声明并初始化
let a = 0,从索引1开始遍历数组,当两指针的值不相同时,移动指针a到a++,并将当前值赋值给指针a,遍历结束后,nums数组的不重复元素将前移,a+1则为不重复元素的个数
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function(nums) {
let a = 0
let len = nums.length
for(let b = 1; b < len; b++) {
if(nums[a] != nums[b]) {
a++
nums[a] = nums[b]
}
}
return a + 1
};
80. 删除有序数组中的重复项 II:给你一个有序数组 nums ,请你 原地 删除重复出现的元素,使得出现次数超过两次的元素只出现两次 ,返回删除后数组的新长度。不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
方法一
思路:
- 思路和前一个差不多,只是从一个重复元素换到了两个,两个元素就往前多对比一个
a-1的值就行 - 说白了就是3种情况
1. a != b
a++
nums[a] = nums[b]
2. a = b
2.1 a - 1 != b
a++
nums[a] = nums[b]
2.2 a - 1 = b
具体代码如下
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
let a = 1
let len = nums.length
for (let b = 2; b < len; b++) {
if (nums[a] != nums[b]) {
a++
nums[a] = nums[b]
} else {
if (nums[a - 1] != nums[b]) {
a++
nums[a] = nums[b]
}
}
}
return a + 1
};
方法二( 另一个作者的题解感觉比我的好 原作者题解 )
思路:
- 题中有说明
1 <= nums.length <= 3 * 104,所以数组最少有2个值,而前两个值是否相同都满足题目要求 - 已经有排序的情况下,
nums[i] === nums[i - 2]则直接nums.splice(i,1)删除原数组中的该值,删除了值,i也要减1
/**
* @param {number[]} nums
* @return {number}
*/
var removeDuplicates = function (nums) {
for (var i = 2; i < nums.length; i++) {
if (nums[i] === nums[i - 2]) {
nums.splice(i,1)
i--
}
}
return nums.length
};