查看原文
其他

539,双指针解删除有序数组中的重复项

博哥 数据结构和算法 2022-05-19

Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul. 

岁月留痕,只及肌肤;激情不再,皱起心灵。

问题描述



给你一个有序数组nums ,请你原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。


不要使用额外的数组空间,你必须在原地修改输入数组并在使用O(1)额外空间的条件下完成。


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


提示:

  • 0 <= nums.length <= 3 * 10^4

  • -10^4 <= nums[i] <= 10^4

  • nums 已按升序排列


双指针解决



因为数组是排序的,只要是相同的肯定是挨着的,我们只需要遍历所有数组,然后前后两两比较,如果有相同的就把后面的给删除。


使用两个指针,右指针始终往右移动

  • 如果右指针指向的值等于左指针指向的值,左指针不动。

  • 如果右指针指向的值不等于左指针指向的值,那么左指针往右移一步,然后再把右指针指向的值赋给左指针。


具体看下视频


来看下代码

1//双指针解决
2public int removeDuplicates(int[] A) {
3    //边界条件判断
4    if (A == null || A.length == 0)
5        return 0;
6    int left = 0;
7    for (int right = 1; right < A.length; right++)
8        //如果左指针和右指针指向的值一样,说明有重复的,
9        //这个时候,左指针不动,右指针继续往右移。如果他俩
10        //指向的值不一样就把右指针指向的值往前挪
11        if (A[left] != A[right])
12            A[++left] = A[right];
13    return ++left;
14}

或者还可以换一种解法,其实原理都是一样的。

1public int removeDuplicates(int[] A) {
2    int count = 0;//重复的数字个数
3    for (int right = 1; right < A.length; right++) {
4        if (A[right] == A[right - 1]) {
5            //如果有重复的,count要加1
6            count++;
7        } else {
8            //如果没有重复,后面的就往前挪
9            A[right - count] = A[right];
10        }
11    }
12    //数组的长度减去重复的个数
13    return A.length - count;
14}


514,双指针解替换后的最长重复字符

497,双指针验证回文串

447,双指针解旋转链表

398,双指针求无重复字符的最长子串


截止到目前我已经写了500多道算法题了,为了方便大家阅读,我把部分算法题整理成了pdf文档,目前有900多页,大家可以在公众号中回复关键字“pdf”即可获取下载链接。


你点的每个赞,我都认真当成了喜欢

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存