LeetCode刷题笔记第26题
题目:
给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
题目来源:力扣(LeetCode)
题目分析:
做题之前一定要将题目分析的细致一些,因为有些条件如果一旦不注意就会造成程序结果出现偏差或者执行不通过。首先该题目给出的是一个有序的数组,从举的例子来看是一个升序数组,然后题目要求我们在原地删除重复元素,也就是不能动用额外的辅助空间,也就是说辅助数组和集合是不能使用的,只能借助于辅助的变量来完成;
既然给定的数组是有序的,那就可以使用快慢指针的做法来解决,其中快指针是用于遍历整个数组的,它在遍历的过程中是会碰到重复的元素的,而慢指针一般情况下不会遍历整个数组,除非整个数组本身就没有重复的元素。算法的整体思路如下:
1、初始化快慢指针,即慢指针初始值为数组首元素的索引,快指针为慢指针的值+1
2、遍历时,比较慢指针和快指针当前所指的值,如果相等则说明有重复元素,快指针值+1
3、如果不等,则说明遇到了不同的值,则先将慢指针向前移动一位,然后将快指针所指的值赋给慢指针当前所指的位置。
4、遍历结束时,新数组的长度即为慢指针+1;
整体的时间复杂度就为O(n),空间复杂度为O(1)。整个过程也不用经常大规模的移动数组元素,有时候我们可能会以为这个算法执行过程中会不会存在后面的值将前面的新数组中的值覆盖的情况,其实是完全不存在的,因为我们要知道慢指针指向的位置永远是新数组的最后一个元素或者马上要成为新数组最后一个元素的位置,而慢指针和快指针之间的“空挡”位置都是已经被遍历过的元素,这些元素要么是已经被移动到了新数组中,要么是重复的元素在快指针遍历时就已经被过滤掉了。
public int removeDuplicates(int[] nums) { if (nums.length <= 1) return nums.length; int slow = 0; int quick = slow + 1; while (quick < nums.length){ if (nums[slow] == nums[quick]) quick ++; else { slow ++; nums[slow] = nums[quick]; quick ++; } } return slow+1; }