【每日刷题】双指针-LC283、LC11、LC42

文章讲述了两种优化的编程解法,分别是解决移动数组中零的O(n)复杂度方法和处理LC11盛最多水的容器以及LC42接雨水问题时,利用左右指针动态计算接取雨水容量的策略。
摘要由CSDN通过智能技术生成

1. LC283.移动零

题目链接
解法一:O(n^2)(不用看了,第一遍尝试的解法,时间复杂度太高)
依次往后遍历,每遇到0,后面的数就挨个往前移一个,fast指向0应该移到末尾的位置,将fast处置0。

class Solution {
    public void moveZeroes(int[] nums) {
        int fast = nums.length - 1;
            for (int i=0; i<fast; i++){
                if (nums[i] == 0){
                    move(i, fast, nums);
                    fast--;
                    i--;
                }
            }
    }
    public void move(int slow, int fast, int[] nums){
        for (int i=slow; i<fast; i++){
            nums[i] = nums[i+1];
        }
        nums[fast] = 0;
    }
}

解法二:O(n)
两个指针,fast,slow。
fast从0开始往后遍历,遇到不是0的数,就存到slow指针指向的地方,slow往前移一个。
相当于fast往前移动着,slow接着fast传过来的不为0的数据。
最后,slow停在末端0串的开头,于是从slow开始遍历到最后一个,全部置0。

class Solution {
    public void moveZeroes(int[] nums) {
        int slow = 0;
        for (int fast=0; fast<nums.length; fast++){
            if (nums[fast] != 0){
                nums[slow] = nums[fast];
                slow++;
            }
        }
        while (slow < nums.length){
            nums[slow] = 0;
            slow++;
        }
    }
}

2. LC11.盛最多水的容器

题目链接
左右指针。
初始:左指针指向0,右指针指向最右边。计算面积。
然后开始向中间移动。
如果移动长边,则水的高度要么是原短边的高度,要么是新的长边移动后得到一个更短的短边的高度,再加上x轴距离也在缩小,所以容积必然更小。
如果移动短边,则短边移动后的高度有可能会变高,容积可能增大。
所以定义while循环,left<right。移动短边,不断向中间聚拢。

class Solution {
    public int maxArea(int[] height) {
        int left = 0;
        int right = height.length - 1;
        int max = 0;
        int cur = 0;
        while (left < right){
            cur = (right - left) * Math.min(height[left], height[right]);
            if (cur > max){
                max = cur;
            }
            if (height[left] > height[right]){
                right--;
            }else{
                left++;
            }
        }
        return max;
    }
}

3. LC42.接雨水

题目描述

贴两个非常易懂的解释:
视频详解
解题思路详解

  1. 首先对于每个位置上能接的雨水量,都取决于这个位置的左边的最大值和右边的最大值。能接的雨水量为min(leftMax, rightMax)。如果height[i] 小于这个最大值,则可以接到雨水 min-height[i]
  2. 左右双指针从两头往中间遍历。left从左往右移动,right从右往左移动。对于left来说,它的leftMax是真实的,因为是一步一步遍历到left得出来的最大值。所以如果leftMax < rightMax,之后的rightMax只可能比现在的rightMax更大,则left能接的雨水的值就能确定了:leftMax-height[left]
  3. 对于right来说,它的rightMax是真实的,因为是一步一步从最右边遍历到right得出来的最大值。所以如果rightMax < leftMax,之后的leftMax只可能比现在的rightMax更大,则right能接的雨水的值就能确定了:rightMax-height[right]
  4. 综上,左右指针分别从左数第二个和右数第二个向中间遍历,遍历过程中更新leftMax和rightMax。若leftMax < rightMax,left位置能接的雨水量确定,left右移。若rightMax < leftMax,right位置能接的雨水量确定,right左移。

最后一个我做的时候踩的坑!left和right在初始化的时候,是x坐标的数值。leftMax和rightMax在初始化的时候,是y坐标的数值。别忘了特殊情况,如果height的长度小于等于2,肯定是接不到雨水的,直接剔除掉这种情况,省的数组越界异常。

class Solution { 
    public int trap(int[] height) {
        if (height.length <= 2){
            return 0;
        }
        int left = 1;
        int right = height.length - 2;
        int leftMax = height[0];
        int rightMax = height[height.length - 1];
        int sum = 0;
        while (left <= right){
            if (leftMax < rightMax){
                if (height[left] < leftMax){
                    sum += leftMax -height[left];
                }else{
                    leftMax = height[left];
                }
                left++;
            }else{
                if (height[right] < rightMax){
                    sum += rightMax - height[right];
                }else{
                    rightMax = height[right];
                }
                right--;
            }
        }
        return sum;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值