双指针算法理解+leetcode例题(Java实现)

双指针算法

  • 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多个数组的多个指针。
  • 若两个指针指向同一数组,遍历方向相同且不会相交,则也称为滑动窗口(两个指针包围的区域即为当前的窗口),经常用于区间搜索
  • 若两个指针指向同一数组,但是遍历方向相反,则可以用来进行搜索,待搜索的数组往往是排好序的。
  • 数组或字符串中,一般为左右指针,链表中一般为快慢指针。

例题

167. 两数之和 II - 输入有序数组

题解

  • 因为数组已经排好序,我们可以采用方向相反的双指针来寻找这两个数字,一个初始指向最 小的元素,即数组最左边,向右遍历;一个初始指向最大的元素,即数组最右边,向左遍历。
  • 如果两个指针指向元素的和等于给定值,那么它们就是我们要的结果。如果两个指针指向元 素的和小于给定值,我们把左边的指针右移一位,使得当前的和增加一点。如果两个指针指向元 素的和大于给定值,我们把右边的指针左移一位,使得当前的和减少一点。
    public int[] twoSum(int[] numbers, int target) {
   
        int[] answer = new int[2];
        int sum;
        //左指针
        int start = 0;
        //右指针
        int end = numbers.length-1;
        //终止条件 start==end 此时已经测试完所有可能的结果
      while(start<end){
   
          sum=numbers[start]+numbers[end];
          if(sum==target){
   
            answer[0]=start+1;
              answer[1]=end+1;
              break;
          }
          if(sum<target) start++;
          //==和>=都会走该句 但前面==后break 故只有>=会走
          else end--;
         
      }
        return answer;
    }
88. 合并两个有序数组

题解

  • 因为这两个数组已经排好序,我们可以把两个指针分别放在两个数组的末尾,即 nums1 的 m − 1 位和 nums2 的 n − 1 位。每次将较大的那个数字复制到 nums1 的后边,然后向前移动一位。 因为我们也要定位 nums1 的末尾,所以我们还需要第三个指针,以便复制。

     public void merge(int[] nums1, int m, int[] nums2, int n) {
         	
         //直接利用m和n指向两个数组已有元素的末尾 pos指向nums1末尾
            int pos = m-- +n-- -1;
            while(m>=0&&n>=0){
         
                //nums2的数较大时移向nums1末尾
                if(nums1[m]<=nums2[n]){
         
                    nums1[pos--]=nums2[n];
                    n--;
                }else {
         
                    nums1[pos--]=nums1[m];
                    m--;
                }
            }
         	//如果 nums1的数字已经复制完,不要忘记把 nums2 的数字继续复制
            while(n>=0){
         
                nums1[n]=nums2[n];
                n--;
            }
        }
    
633. 平方数之和

题解

  • 这是一道经典的双指针相向而行的题目,但是要注意剪枝,就是right部分一定小于等于c的平方根,所以首先要把right部分确定下来,左右双向而行就可,大了就right左移,小了就left右移,直到相遇或者平方和为c,代码如下:
  • 起始条件:左指针 0 右指针 c的平方根 (如果能与两个数的平方和相等,两个数一定在该范围内,在这个范围内进行双指针搜索),左右指针分别指示着较小和较大的数
  • 终止条件:左指针大于右指针 或 c与两个数的平方和相等
    public boolean judgeSquareSum(int c) {
   
        int middle = (int) Math.sqrt(c);
        int  left = 0;//左指针
        int  right = middle;//右指针 
        long  sum;//避免结果溢出
        while(right>=left){
   
            sum=left*left+right*right;
            if(sum==c) return true;
            if(sum>c) right--;
            else left++;
        }
        return false;
    }
  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值