leetcode-删除有序数组中的重复项

·  阅读 370
leetcode-删除有序数组中的重复项

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

今天下午评审PRD搞了一整个下午。不知道大家有没有这样的感受,工作中的会议越来越多,可以花在其他事情上的精力越来越少,明明是互联网公司,也渐渐有了国企文山会海的味道。最近一段时间对这个问题也进行了思考,怎样高效的开会。我认为其中有一点非常重要,会议前把要讨论的议题发出来,PRD评审就先把PRD稿发出来,参会人先自己预习一下,有疑问可以先写下来,会议的时候集中讨论,这样会有的放矢,把时间集中在有争议的点上,大家都完全理解一致的点,就不需要再全部重复一遍了。就像上学的时候,老师要求先预习一下功课,上课的时候带着问题去听课,学习的效果会更好。不过回到会议的问题上,很难要求每个人都做了充分的预习,不预习的人无法跳过共识的部分,不然会有缺失,难以理解整体,这样就造成了又回到原始的状态,而且一个会议接着一个会议的时候,就更难实行了,陷入恶性循环。

这个问题暂时没想到比较好的解决方案,目前只能先要求发起人约会议的时候先把议题发出来,也挺想看看其他人是否有好的想法。

不管怎么样,技术还是要继续精进的,今天做leetcode的第26题。

题目

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

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

你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

 

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

思路

双指针的典型例题,应该语言描述就能明白:

  1. 定义2个指针fast和slow,都指向下标为1的节点
  2. 当num[fast]==num[fast-1]时,fast指针向前移动1位,slow不动
  3. 当num[fast]>num[fast-1]时,num[slow] = num[fast],fast和slow都向前移动1位

便于理解还是放1张图,红色是fast指针,黑色是slow指针:
快慢指针.png

为什么可以这么做呢?
num已经从小到大排序好了,我们只要找出不重复的数字即可。每次fast都会向前移动1位,而slow可能不动,fast永远会在slow前面,最多是相同位置。当num[fast]==num[fast-1]时,代表这个数字已经出现过了,不需要再重新记录,而num[fast]>num[fast-1]时,代表这个数字是新出现的,需要记录下来。

为什么初始指向下标为1的节点的?
正常应该指向下标为0的节点的,但是下标为0的节点,这个数字对于这个数组来说,一定是新出现的,所以这里其实是隐含执行了1次步骤3

Java版本代码

class Solution {
    public int removeDuplicates(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            return len;
        }
        int ans = 1;
        for (int i = 1; i < len; i++) {
            if (nums[i] > nums[i-1]) {
                nums[ans++] = nums[i];
            }
        }
        return ans;
    }
}
复制代码
分类:
后端
标签: