Leetcode刷题系列:删除有序数组中的重复项

219 阅读2分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

题目

给你一个有序数组 nums,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。 不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成

说明: 为什么返回数值是整数,但输出的答案是数组呢? 请注意,输入数组是以**「引用」**方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re…

实例:

示例 1:

输入:nums = [1,1,2] 输出:2, nums = [1,2] 解释:函数应该返回新的长度 2 ,并且原数组 nums 的前两个元素被修改为 1, 2 。不需要考虑数组中超出新长度后面的元素。

示例 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 。不需要考虑数组中超出新长度后面的元素。

理解题意:

题目主要内容:

  • 删除重复出现的元素,保证每个元素出现一次,返回移除后的新数组长度

附加要求:

  • 在原数组中的进行操作,时间复杂度为 O(1)

其他条件:

  • 给定一个排序数组、重复元素都是相邻的、不需要考虑数组中超出新长度后的元素

细节点:

  • 数组为空的情况
  • 数组小标边界问题
  • 元素重复次数没有限定

实现方案1 :暴利破解:遍历 + 比较

呼呼:没有什么是遍历解决不了的事情~

实现逻辑:

  • 设置 长度变量:初始化,数组长度
  • 循环遍历,进行相邻元素比较
    • 若不相等:则 i++ 往后进行遍历
    • 若相等:
      • 则 相邻数据,之后的元素都向前位移一位
      • 位移完成后,将数组长度减1
public static int removeDuplicates(int[] nums) {
    int arrLength = nums.length;
    // 循环遍历
    for (int i = 0; i < arrLength - 1; ) {
        // 比较相邻两个元素的数据是否相同
        if (nums[i] != nums[i + 1]) {
            // 不相同,向后遍历
            i++;
        } else {
            // 相同,将后续元素都向前移动1位
            for (int j = i + 1; j < arrLength - 1; j++) {
                nums[j] = nums[j + 1];
            }
            // 每移动一位即,删除一个元素
            arrLength--;
        }
    }
    return arrLength;
}

实现方案2 :双指针

实现逻辑:

  • 通过双指针 记录 目标位置:0 和 待移动元素的位置:1
  • 两指针数据进行比较:
    • 数据相等:则:待移动元素的位置 向后移一位
    • 数据不同:则:目标位置向后移动一位,并 将待移动元素,移动到目标位
  • 相关注意事项:
    • 如果 目标位置 和 待移动位置的下标一直,则跳过赋值
  • 新数组的长度:
    • 即循环结束后,目标位置即是最后一位元素的下标,所以长度为 目标元素下标 + 1
 public static int removeDuplicates(int[] nums) {
    // 目标位置 指针
    int target = 0;
    for (int i = 1; i < nums.length; i++) {  // i:待移动元素指针
        // 当 目标数据 和 待移动元素中的数据不同,并且 目标位置向后移动的位置 和 待移动位置不同的时候
        if (nums[target] != nums[i] && ++target != i) {
            // 进行对数据赋值
            nums[target] = nums[i];
        }
    }
    // 返回目标下标 + 1
    return target + 1;
}


github 地址

案例地址