前言
一个小伙伴说希望成立一个刷题小组,本就着富强、民主、文明、和谐,倡导自由、平等、公正、法治,倡导爱国、敬业、诚信、友善,积极培育社会主义核心价值观,我答应他了。
因为也没有刷过题,比较菜。然后就看了下别人家的孩子怎么刷题的,这里附上链接。
朝花夕拾 - 2019 总结(附 283 道 LeetCode 题解)
题目描述:
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k 。
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
判题标准:
系统会用下面的代码来测试你的题解:
int[] nums = [...]; // 输入数组
int[] expectedNums = [...]; // 长度正确的期望答案
int k = removeDuplicates(nums); // 调用
assert k == expectedNums.length;
for (int i = 0; i < k; i++) {
assert nums[i] == expectedNums[i];
}
如果所有断言都通过,那么您的题解将被 通过。
输入:nums = [1,1,2]
输出:2, nums = [1,2,_]
解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 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 。不需要考虑数组中超出新长度后面的元素。
/**
* @param {number[]} nums
* @return {number}
* 经历过之前没读懂题意,导致答案无法通过,浪费了时间,所以我们一定要吸取教训,仔细读题。
* 读题可知,我们需要对数组去重,并使用原数组内存操作。
* 返回删除后数组长度,就是原数组减去重复元素个数。
* 前部分是新去重数组,后面是重复数组元素丢弃区。
* 因为不能使用额外数组空间,所以我们不能用js删除数组api了,这就很尴尬。
* 本着写不出来看答案的优秀学习方法,我们了解到这道题要用到双指针中的快慢指针。
*
*/
/**
* @description: 双指针 TC:O(n) SC:O(1)
* @param {*} nums 输入数组
* @return {*}
*/
function removeDuplicates(nums){
/**
* 该方案利用双指针的方式,定义两个指针(low初值0,fast初值1),当两指针所指元素相同时,将fast指针继
* 续向右移动直至遇到不同元素时(此时low与fast则会拉开一个区间,该区间的元素则为需要删除的相同的元
* 素),将low指针向右移动一位,并将其赋值为fast指针所指元素(此时0到low指针所在区间的元素则是不重
* 复的元素),当fast指针超出数组范围则终止循环,此时low位置+1则为去重后数组长度。
*/
// 如果数组长度不大于1,无需去重直接返回即可
if(nums.length<=1)return nums.length;
// 定义两个指针
let fastPoint=1,lowPoint=0;
// 当fast指针超出数组范围则终止循环
while(fastPoint<nums.length)
{
// 当两指针所指元素不同
if(nums[lowPoint]!=nums[fastPoint])
{
// 将low指针向右移动一位
lowPoint++;
// 并将其赋值为fast指针所指元素
nums[lowPoint]=nums[fastPoint];
}
// 继续移动fast指针
fastPoint++;
}
return lowPoint+1;
}
我们平时都喜欢用遍历,其实最早我就想着遍历一次,重复的替换成标记,然后再次遍历把标记交换位置正向排序,遇到就是最大值。
双指针这个遍历一定没有想到吧。
我们看到图解