双指针在数组中的应用

(1)双指针的作用:将时间复杂度由O(n^2)降为O(n)

(2)双指针的类型:快慢指针,左右指针,滑动窗口

(3)时间换空间常用双指针,位运算,空间换时间常用哈希表

(4)看见有序,要想双指针压缩,二分搜索


(4)快慢指针:删除数组元素,移动数组元素

例题:27. 移除元素 - 力扣(LeetCode)

283. 移动零 - 力扣(LeetCode)

思路:要求不适用额外数组空间,使用常数级空间并原地修改

根据题意,我们只能将原数组中符合要求的移到前面,后面的不用管

但是数组中的移动常常是隐藏的覆盖!

就是两个for循环,外层用来遍历找到要移除元素的位置,内层负责覆盖(nums[i]=nums[i+1])

看见两个for循环,我们就要警惕看看是否能用双指针来优化时间复杂度

快慢指针思路:快指针用来遍历,慢指针用来被覆盖,数组前半部分一定是我们需要的元素,所以只有在快指针指的值不等于val时,array[left]=array[right].

class Solution {
    public int removeElement(int[] nums, int val) {
        int fastIndex = 0;
        int slowIndex;
        for (slowIndex = 0; fastIndex < nums.length; fastIndex++) {
            if (nums[fastIndex] != val) {
                nums[slowIndex] = nums[fastIndex];
                slowIndex++;
            }
        }
        return slowIndex;
    }
}

(5)左右指针:

例题:125. 验证回文串 - 力扣(LeetCode)      977. 有序数组的平方 - 力扣(LeetCode)

有序数组的平方:复杂的情况就是前面负数,后面正数

但是注意:任何情况下的平方后的最大值永远只会出现在两侧

class Solution {
    public int[] sortedSquares(int[] nums) {
        int n = nums.length;
        int[] ans = new int[n];
        for (int i = 0, j = n - 1, pos = n - 1; i <= j;) {
            if (nums[i] * nums[i] > nums[j] * nums[j]) {
                ans[pos] = nums[i] * nums[i];
                ++i;
            } else {
                ans[pos] = nums[j] * nums[j];
                --j;
            }
            --pos;
        }
        return ans;
    }
}


(6)滑动窗口

209. 长度最小的子数组 - 力扣(LeetCode)

先增大right直到大于目标值,在增大left缩小区间(也可以尝试前缀和+二分查找)

class Solution {
    public static int minSubArrayLen(int target, int[] nums) {
        int left=0,right=0;
        int result=Integer.MAX_VALUE;
        int sum=0;
        while(right<nums.length){//两次while循环
            sum=sum+nums[right];
            while(sum>=target){
                result=Math.min(result,right-left+1);
                sum=sum-nums[left];
                left++;//先记再减后改
            }
            right++;
        }
    if(result!=Integer.MAX_VALUE){
        return result;
    }else{
        return 0;
    }
        
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值