[LeetCode][Golang] 26. 删除有序数组中的重复项

【[LeetCode][Golang] 26. 删除有序数组中的重复项】题目:
给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
由于在某些语言中不能改变数组的长度,所以必须将结果放在数组nums的第一部分。更规范地说,如果在删除重复项之后有 k 个元素,那么 nums 的前 k 个元素应该保存最终结果。
将最终结果插入 nums 的前 k 个位置后返回 k
不要使用额外的空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。

  • 0 <= nums.length <= 3 * 104
  • -104 <= nums[i] <= 104
  • nums 已按 升序 排列
题解:
首先,这是一道数组类的简单算法题。我们明确循环不变式(loop invariant)的概念,即一组在循环体内、每次迭代均保持为真的性质。
先贴代码:(GO语言)
func removeDuplicates(nums []int) int { n := len(nums) if n < 2 { return n } slow, fast := 1, 1 for fast < n { if nums[fast-1] != nums[fast] { nums[slow] = nums[fast] slow++ } fast++ } return slow

我们设置的循环不变式:slow指针之前的数组元素(不包含目前所指元素)不重复。同时使用快慢指针的方式。
  • 初始slow设为1,即nums[1]之前的元素不重复,由于nums[1]之前最多有一个元素,一定不会出现重复,所以slow位置满足不变式要求。
  • 接下来的循环中,如果nums[fast]nums[fast-1]不相同,由于数组升序,则将nums[fast]赋值给nums[slow]后后移slow,结束本次循环。如果nums[fast]nums[fast-1]相同,则直接结束本次循环。每次循环,slow位置均满足不变式要求。
  • 最终fast指针遍历完数组元素后,结束整个循环,slow位置满足不变式要求。
因此在循环结束后,slow左侧元素均为不重复元素,符合算法要求。
复杂度分析:
  • 时间复杂度:O(n),其中 n 是数组的长度。快指针和慢指针最多各移动 n 次。
  • 空间复杂度:O(1)。只需要使用常数的额外空间。

    推荐阅读