双指针问题

  1. leetcode11.https://leetcode-cn.com/problems/container-with-most-water/盛最多容器的水
  2. leetcode 283.https://leetcode-cn.com/problems/move-zeroes/移动零
  3. leetcode15.https://leetcode-cn.com/problems/3sum/三数之和

前两题用到双指针,双指针是一种技巧。双指针分为对撞指针和快慢指针,需要注意的是两种指针的区别,包括(1)双指针的初始位置;(2)双指针的移动方式(什么时候移动,移动方向,移动间隔,移动之前需要判断是否会越界);(3)遍历的结束条件。基本上解题套模板时也是这三点明确了就很好写。数组问题可以参考链接https://blog.csdn.net/justidle/article/details/106297779

//对撞指针模板
function fn(int list[], int len) {
  int left = 0;
  int right = len - 1;
 
  //遍历数组
  while (left <= right) {
    left++;
    // 一些条件判断 和处理
    ... ...
    right--;
  }
}

/*1.盛最多水的容器。根据需要注意的三点,直接套模板就可以写出来。*/
/*2.需要注意的细节:用到了Math类的方法,一开始不知道用Math.min()和Math.max()函数,直接手动比较大小,代显得很冗余*/
class Solution {
    public int maxArea(int[] height) {
        //step1.初始值
        int left = 0, right = height.length - 1, ans = 0, area = 0;

        //step2.结束条件,遍历
        while(left < right){
        //step3.移动方式
        area = Math.min(height[left], height[right]) * (right - left);
        ans = Math.max(ans,area);
        if(height[left] <= height[right]){
        left ++;
            }else right --;
        }
        return ans;
    }
}

【移动零】这道题用到的是快慢指针,题本身不难,但是网上有两种高票解法很有意思,用到的思想,一个是慢指针标记不为0的元素相对位置,一个是用到快排思想,交换快慢指针的元素。【之前以为if、while等流程语句很简单,但做题的时候会常常出现这些地方得逻辑错误;另外一点,做完后发现对于题目给的参数没有判断,这也是常忽略的地方,需要对给的参数,如数组,要判断数组长度是否符合解题条件,数组是否为null...;还有就是注意题中要求,是不是要求空间复杂度,如不许额外开辟空间什么的...

/*快慢指针模板*/
function fn(LinkList *list, int len) {
  int slow = 0;
  int fast = 1;
 
  //遍历数组
  while (slow != fast) {
    slow++;
    // 一些条件判断 和处理
    ... ...
    fast+=2;
  }
}

/*思路1:用j标记不为零的元素*/
class Solution{
    public void moveZeroes(int[] nums) {
        //1.初始位置
        int i = 0;
        int j = 0;
        //2.结束条件
        for(; i < nums.length; i ++){
        int temp = 0;
        if(nums[i] != 0)
        //3.移动方式 (只要快指针对应的元素不为0,快指针对应的元素赋给慢指针,如果快慢指针不相等,则将快指针对应的元素置0,同时慢指针要向前移动)   
            temp = nums[i];
            nums[j] = temp;
            j ++;
        if(i != j)
            nums[i] = 0;
        }
    }
}

/*思路2:受快排启发,交换法*/
class Solution{
    public void moveZeroes(int[] nums) {
        //1.初始位置 2.结束条件
        for(int i = 0, j = 0; i < nums.length; i ++){
            int temp = 0;
            //3.(慢指针)移动方式--只要快指针遍历到的元素不为0,就与慢指针对应的元素交换、同时慢指针向前移动。因为所有的0都是一个0
            if(nums[i] != 0){
                    temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                    j ++;
            }
        }
    }
}

3.三数之和这个问题属于经典的老题,暴力解的时间复杂度为O(n^3),经典解法是可以将时间复杂度降到O(n^2)。算法真的等于数学,总能勾起做数学题时讨论边界条件的场景...

/*三数之和:摘抄国际站大佬的解法*/
/*这道题也用到碰撞指针,*/
1.public List<List<Integer>> threeSum(int[] num) {
2.    Arrays.sort(num);
3.    List<List<Integer>> res = new LinkedList<>();  //创建一个List,由于List是抽象接口,只能实现一个LinkedList或者ArrayList...
4.    for (int i = 0; i < num.length-2; i++) {   //三数问题转换成【1个数+两个数之和】问题...
5.        if (i == 0 || (i > 0 && num[i] != num[i-1])) { //这里的&&之后是为了去重,如果num[i]元素与num[i - 1]相同,就没必要再求解了,符合题中要求:不重复
6.            int lo = i+1, hi = num.length-1, sum = 0 - num[i];
7.            while (lo < hi) {
8.                if (num[lo] + num[hi] == sum) {
9.                    res.add(Arrays.asList(num[i], num[lo], num[hi])); //Arrays.asList()将数组转换成链表,这个函数是盲区....
10.                    while (lo < hi && num[lo] == num[lo+1]) lo++;  //第10行和第11行,一开始没转明白为什么num[lo] == num[lo+1],lo还要++,把num[lo] == num[lo+1]理解成lo已经是移位了,其实while中只是判断...,然后如果lo和lo+1位置元素相同,那lo++就和lo相同,lo需要‘再’+1,与12行正好对应。   而且这里还要判断++后lo和hi的关系,是否符合循环条件了
11.                    while (lo < hi && num[hi] == num[hi-1]) hi--;
12.                    lo++; hi--;
13.                } else if (num[lo] + num[hi] < sum) lo++;
14.                else hi--;
15.           }
16.        }
17.    }
18.    return res;
19.}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值