高频刷题-双指针法(two-pointers)专题

双指针法是一个可以是一个算法模板,经常被运用在有序的数组或列表中。和滑动窗口不同的是,此时的双指针是从两侧到中间,通俗点也可以称为夹逼法。例如,从一个有序数组中找到符合一定条件的元素组。

直接遍历整个集合,需要进行O(n^2)或者O(n^3)复杂度的遍历。而双指针的夹逼法,通常可以只遍历一次即可找到结果,有效的节省了时间复杂度和空间复杂度。

确定何时使用双指针方法的方法:

      

  1. 它将处理排序数组(或链表)并需要找到一组满足某些约束的元素的问题

数组中的元素集是一对、三元组,甚至是子数组。

https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/

该题是最典型的双指针夹逼法去求解的题。和上图示意一致。直接用双指针,从头和尾往中间查找。代码如下:

public int[] twoSum(int[] numbers, int target) {
        int left = 0, right = numbers.length - 1;
        int[] res = new int[2];
        
        while(left <= right) {
            if (numbers[left] + numbers[right] == target) {
                res[0] = left + 1;
                res[1] = right + 1;
                break;
            } else if (numbers[left] + numbers[right] < target) {
                left++;
            } else {
                right--;
            }
        }
        
        return res;
}

求解的效果是很不错的:

https://leetcode.com/problems/squares-of-a-sorted-array/

这个也没啥好说的,因为是有序,但是存在负数,所以平方后的排序一定是头和尾的绝对值大小,大的平方也大,这样可以确定最后保存的位置。

public int[] sortedSquares(int[] nums) {
        // 采用两个指针,一个开头,一个结尾
        // 对比两个指针的squaring值的大小,从最后一个元素开始,大的元素放到最后
        // 如果是右侧值大,则right--,左侧大,则left++; 
        
        int size = nums.length;
        int left = 0, right = size - 1;
        int[] res = new int[size];
        
        while (left <= right) {
            if (Math.abs(nums[right]) > Math.abs(nums[left])) {
                res[--size] = nums[right] * nums[right];
                right--;
            } else {
                res[--size] = nums[left] * nums[left];
                left++;
            }
        }
        return res;
    }

另外还有3 sum : https://leetcode.com/problems/3sum/

Trapping Rain Water :  https://leetcode.com/problems/trapping-rain-water/

等一些题可以采用该方法解决。

双指针法广泛的用于滑动窗口,二分查找,链表遍历(快慢指针)和本文提到的夹逼法,而它们的不同在于指针移动的顺序不同,可以多对比学习。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值