Leetcode剑指offer刷题day02

Leetcode剑指offer刷题day02

主要内容,双指针+滑动窗口
题目一描述:

给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

题目分析:

暴力解法,直接枚举所有的连续子数组,判断其是否满足要求,时间复杂度为O(n^2)。

双指针+滑动窗口的思想也不难想到,观察题目描述要求的连续子数组,因此考虑当我们找到一个连续子数组,nums[i],nums[i+1]…nums[j],它们的和大于目标数target,那么此时我们可以固定窗口的右边界,尝试缩短左边界,判断是否缩短之后也满足要求,一直缩短,知道当前窗口的和值小于target,才考虑移动右边界。(这里可以理解为找到以nums[j]为结尾的连续子数组)。因此解题思路:定义两个指针l和r,初始时指针都指向下标为0的位置,在每一次迭代的过程中加上nums[r]的值,当累加和sum>=target时,就开始考虑缩短左边界了,缩短左边界后不满足要求了,就开始移动右边界,终止条件为右边界出界。

代码实现:
 //双指针+滑动窗口,求最小连续子数组的和,满足和>=target
    public int minSubArrayLen(int target, int[] nums) {
    
    
        int n=nums.length;
        int l=0;
        int r=0;
        int sum=0;
        int res=Integer.MAX_VALUE;
        while (r<n){
    
    
            sum+=nums[r];
            while (sum>=target){
    
    
                res=Math.min(res,r-l+1);
                sum-=nums[l];
                l++;
            }
            r++;
        }
        return res==Integer.MAX_VALUE?0:res;
    }
注意,滑动窗口需要注意的地方是当前维护的窗口是 l…r之间的数,l==r时当前窗口还维持着一个数,并非没有数,终止条件一般为右指针出界。

该题可以用双指针+滑动窗口,在于nums数组中的每个数是大于0的。否则使用滑动窗口的思想会出错。

题目二描述:

给定一个正整数数组 nums和整数 k ,请找出该数组内乘积小于 k 的连续的子数组的个数。

题目分析:

在分析了上一道题连续子数组的和,这一道题则是连续子数组的积。我们还是考虑对于一个连续的子数组nums[i],nums[i+1]…nums[j-1],如果nums[j]加到该连续子数组中,使得它们的积小于k,那么对于加进来的nums[j],可以使原来的满足条件的方案数加上j-i+1种(这里依然可以理解为加上以nums[j]为结尾的满足条件的连续子数组的个数)。这里需要注意的是如果当个数就大于target,就要考虑从该数的下一个数重新开始,累计积重置为1,两个指针置于同一个位置。当当前窗口中的所有数的累积大于等于k时,就要考虑固定右边界,缩小左边界,直到当前窗口的大小为0或者右边界的下一个数能够加到当前窗口中(计算累积小于k时)。

代码实现:
//滑动窗口的解决办法,双指针
    public int numSubarrayProductLessThanK(int[] nums, int k) {
    
    
        int n = nums.length;
        int l=0;
        int r=0;
        int res=0;
        int ans=1;
        while (r<n){
    
    
            while (r<n&&ans*nums[r]<k){
    
    
                ans=ans*nums[r];
                res+=r-l+1;
                r++;
            }
            //如果单个数比k还要大的话,就要考虑从下一个数重新开始
            if(l==r){
    
    
                ans=1;
                l++;
                r=l;
            }else {
    
    
                ans/=nums[l];
                l++;
            }
        }
        return res;
    }

猜你喜欢

转载自blog.csdn.net/weixin_46202290/article/details/123143566