LintCode双指针/滑动窗口/Two Sum类型题总结

双指针题算是数组类型题目的一个子模块了。373. Partition Array by Odd and Even把一个数组划分为奇数在前偶数在后的状态,要求in place。很简单,就用双指针法,让两个指针从两头往中间扫描,当左边是偶数右边是奇数时就交换,直到左右指针相遇为止。 public void partitionArray(int[] nums) { in
摘要由CSDN通过智能技术生成

双指针题算是数组类型题目的一个子模块了。

373. Partition Array by Odd and Even

把一个数组划分为奇数在前偶数在后的状态,要求in place。很简单,就用双指针法,让两个指针从两头往中间扫描,当左边是偶数右边是奇数时就交换,直到左右指针相遇为止。

    public void partitionArray(int[] nums) {
        int left = 0, right = nums.length - 1;
        while (left < right) {
            // 左边是奇数的话就自增,直到找到前面的偶数
            while (nums[left] % 2 == 1) {
                left++;
            }
            // 右边是偶数的话就自减,直到找到后面的奇数
            while (nums[right] % 2 == 0) {
                right--;
            }
            if (left < right && nums[left] % 2 == 0 && nums[right] % 2 == 1) {
                int tmp = nums[left];
                nums[left] = nums[right];
                nums[right] = tmp;
            }
        }
        return;
    }

539. Move Zeroes

把一个数组的所有0移动到末尾,且不改变原数组非零元素之间的相对位置。要求in place进行。

第一种方法是双指针移动法,left和right指针一开始都置为起始元素,然后让right去遍历寻找非0元素。找到了非0元素后,就把两个指针的元素互换,使得后面的right指向的非0元素可以把left指向的0给替换掉。

交换完后,此时的left应该指向下一个0元素,所以left要自增。同时外层循环让right自增,继续去寻找下一个非0元素:

    public void moveZeroes(int[] nums) {
        int left = 0, right = 0;
        while (right < nums.length) {
            // right指针找到一个非0的数,就与left指针交换
            if (nums[right] != 0) {
                int tmp = nums[left];
                nums[left] = nums[right];
                nums[right] = tmp;
                // 交换后,left自增
                left++;
            }
            right++;
        }
        return;
    }

第二种方法是双指着压缩法:实际上就是将所有的非0数向前尽可能的压缩,最后把没压缩的那部分全置0就行了。比如103040,先压缩成134,剩余的3为全置为0。过程中需要一个指针记录压缩到的位置。

从前往后遍历数组,遇到一个非0数组,就往pos那个位置给填上,填完后pos就自增。然后外层循环的index也要自增。最后把pos之后的所有非0元素置为0:

    public void moveZeroes(int[] nums) {
        int pos = 0, index = 0;
        
        while (index < nums.length) {
            if (nums[index] != 0) {
                nums[pos++] = nums[index];
            }
            index++;
        }
        
        while (pos < nums.length) {
            nums[pos] = 0;
            pos++;
        }
    }

172. Remove Element

给定一个数组和一个整数elem,要求吧数组中所有等于elem的元素都删除,并返回新数组的长度。比如:Given an array [0,4,4,0,0,2,4,4], value=4 return 4 and front four elements of the array is [0,0,0,2]

这道题的解法和上道题的方法二是一模一样的。双指针压缩法,把所有不等于elem的元素往前压缩:

    public int removeElement(int[] A, int elem) {
        int pos = 0;
        for (int i = 0; i < A.length; i++) {
            if (A[i] != elem) {
                A[pos++] = A[i];
            }
        }
        return pos;
    }


100. Remove Duplicates from Sorted Array

给定一个有序数组,要求去除其中重复的元素。与其说是删除重复元素,倒不如说是把unique的元素全部放到前面。

这道题跟上面两道题有异曲同工之妙,基本思路是一致的。双指针压缩法。我把所有unique的元素尽量往前面放。

左指针pos用于放置元素,右指针i用于从前往后扫描。当扫到一个跟pos不同的元素时,我就可以把它放到pos后面。直到扫描完最后一个元素,这个时候数组的前pos+1个元素就是不包含重复元素的原数组的压缩版了:

    public int removeDuplicates(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int pos = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != nums[pos]) {
                pos++;
                nums[pos] = nums[i];
            }
        }
        return pos + 1;
    }


101. Remove Duplicates from Sorted Array II

跟上道题不同之处在于允许2次重复的出现。但是重复超过2次就不行了。基本思路还是一样的。

pre指针用于记录位置值以及放置unique元素,cur指针用于遍历,搜索与pre不同的元素。由于允许出现2次重复,所以需要一个变量count来统计重复次数。

因为数组是有序的,所以可以从前往后遍历的同时记录count。

如果cur和pre不同,则结束计数器(即count置为1),同时把后面那个跟pre不同的元素(即cur)移动到pre的后面。然后把pre指向下一个元素。

如果cur和pre相同,并且此时还可以继续计数,则统计重复次数(即count++)。并且把cur移动到pre的后面。然后把pre指向下一个元素。

外层循环则继续移动cur指针来遍历

    public int removeDuplicates(int[] nums) {
        i
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值