首页 > 其他分享 >【LeetCode数组#4】长度最小的子数组

【LeetCode数组#4】长度最小的子数组

时间:2023-01-08 19:33:13浏览次数:61  
标签:target nums int res sum 数组 长度 LeetCode

长度最小的子数组

力扣题目链接(opens new window)

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

示例:

输入:s = 7, nums = [2,3,1,2,4,3] 输出:2 解释:子数组 [4,3] 是该条件下的长度最小的子数组。

初见思路

题目给的输入有两个,一个是数组nums,另一个是目标和target。我们需要找到数组中的一个连续子数组,其相加和为target,且所需数组元素最少

两个问题:
1、寻找一个子数组,相加结果等于target

2、该子数组是所有可能数组中最小的

双指针好像不太行,用暴力破解试试

那就用两层for循环,第一层用于控制子数组的起始位置,第二层是子数组的结束位置【感觉本质上还是双指针。。。】

Java版(超时)

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int sum = 0;
        int subLeng = 0;//用于记录子串长度
        int res = Integer.MAX_VALUE;//将res设置为int的最大值
        for(int i = 0; i < nums.length; i++){
            sum = 0;
            for(int j = i; j < nums.length; j++){
                sum += nums[j];
                if(sum >= target){
                    subLeng = j - i + 1;
                    res = res < subLeng ? res : subLeng;//满足最小子串条件的才保留,显然如果出现subLeng一定会保存的因为不可能有比res大的值
                    break;
                } 
            }
        }
        return res == Integer.MAX_VALUE ? 0 : res;//判定当前res是否还为初始值,是就输出0
    }
}

不负众望的超时了,这也正常,毕竟两个for循环已经是O(n*n)的时间复杂度了

常规思路

这里就需要使用数组操作中的一个重要方法:滑动窗口

其本质上还是需要两个玩意去代表子数组的起始和结束位置

只不过使用滑动窗口方法我们可以在一个for循环中就实现上述功能,从而优化了时间复杂度

上面的描述更像双指针了,实际上滑动窗口确实就是双指针的一个变种,或者说只要你乐意,在一个数组上操控两个下标的方法都可以是双指针。

那么怎么做呢?

既然是双指针,那么肯定先确定两个指针各自需要干什么

设这里有两个指针left、right,分别表示窗口的左边界右边界

和之前的双指针用法类似,将某个指针放入for循环中作为遍历时的下标【那肯定是右边界比较合适】

当for循环不断移动右边界的位置时,我们同时计算两个边界内(即窗口内)的数的和

如果当前窗口中元素的和满足target,记录下其长度,与res比较【res的初始值设为整型下的最大值】

如果当前子串长度小于res,那么将更新res为当前子串的长度值【肯定更新啊,res都设成最大了,来什么值都会更新的】

然后移动左边界left,继续计算,不满足条件就移动右边界

总而言之,就是当条件不满足时,移动右边界去遍历整个数组,遇到条件满足的子数组,计算并更新res,然后移动左边界,重复上述过程。

以题目中的示例来举例,s=7, 数组是 2,3,1,2,4,3,来看一下查找的过程:

209.长度最小的子数组

解题模板

滑动窗口的代码中的关键点如下:

  • 滑动窗口算法是基于双指针思想的一种算法
  • 用于保存记录窗口内数值和的变量res应该设置为整型的最大值
  • while缩小窗口大小

Java版

ps:

  • 取最大值res使用Integer.MAX_VALUE
  • 使用Math.min比较并更新res(Java版)
  • Java下三目运算符:(关系表达式) ? 表达式1:表达式2;
先执行关系表达式,看其结果是true还是false
如果是true,则执行表达式1
如果是false,则执行表达式2
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int sum = 0;
        int subLeng = 0;
        int left = 0;
        int res = Integer.MAX_VALUE;//将res设置为int的最大值
        for(int right = 0; right < nums.length; right++){
            sum += nums[right];//累加当前窗口内的数值
            while(sum >= target){//当和大于等于target时,记录并更新res
                subLeng = right - left + 1;
                res = Math.min(res, subLeng);//更新res
                sum -= nums[left++];//移动左边界缩小窗口,此处为算法核心
            }
        }
        return res == Integer.MAX_VALUE ? 0 : res;//判定当前res是否还为初始值,是就输出0
    }
}

Python版

ps:

  • Python中res需要取无限大的值,用float("inf")实现
  • range(len(nums))生成用于遍历的迭代体
  • 比较子串长度时使用min函数
  • 注意Python下三目运算符的写法:[statement_1] if [expression] else [statement_2]
class Solution:
    def minSubArrayLen(self, target: int, nums: List[int]) -> int:
        sum = 0
        left = 0  # 窗口左边界
        res = float("inf")  # 无限大的数,相当于java中的Integer.MAX_VALUE
        for right in range(len(nums)):
            sum += nums[right]  # 累加窗口内的值
            while sum >= target:
                res = min(res, right - left + 1)  # 比较当前子串和res的长度,取最小值
                sum -= nums[left]
                left += 1
        return 0 if res == float("inf") else res  # 判断res是否为初值

标签:target,nums,int,res,sum,数组,长度,LeetCode
From: https://www.cnblogs.com/DAYceng/p/17035161.html

相关文章

  • [leetcode每日一题]1.8
    ​​2185.统计包含给定前缀的字符串​​难度简单28给你一个字符串数组 ​​words​​ 和一个字符串 ​​pref​​ 。返回 ​​words​​ 中以 ​​pref​​ 作为 ......
  • 【优先队列】LeetCode 23. 合并K个升序链表
    题目链接23.合并K个升序链表思路把全部结点放入优先队列中,然后再依次组成新链表代码classSolution{publicListNodemergeKLists(ListNode[]lists){......
  • LeetCode 236_二叉树的最近公共祖先
    LeetCode236:二叉树的最近公共祖先题目给定一个二叉树,找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树T的两个节点p、q,最近......
  • LeetCode 887. 鸡蛋掉落-题解分析
    题目来源887.鸡蛋掉落题目详情给你k枚相同的鸡蛋,并可以使用一栋从第1层到第n层共有n层楼的建筑。已知存在楼层f,满足 0<=f<=n,任何从高于f的楼层落......
  • 【优先队列】LeetCode 347. 前 K 个高频元素
    题目链接347.前K个高频元素思路前k大模板题代码classSolution{publicint[]topKFrequent(int[]nums,intk){PriorityQueue<Map.Entry<Integer,......
  • 【优先队列】LeetCode 973. 最接近原点的 K 个点
    题目链接973.最接近原点的K个点思路使用优先队列处理前k大问题代码classSolution{classNode{intx;inty;doubledistance;......
  • LeetCode每日一题1.8
    2185.CountingWordsWithaGivenPrefixhttps://leetcode.cn/problems/counting-words-with-a-given-prefix/官方题解:https://leetcode.cn/problems/counting-words-w......
  • [C++/Java/Py/C#/Ruby/Swift/Go/Scala/Kotlin/Rust/PHP/TS/Elixir/Dart/Racket/Erlang
    目录题解地址代码cppjavapython3C#rubyswiftgolangscalakotlinrustphptypescriptelixirdartracketerlang题解地址https://leetcode.cn/problems/counting-words-with-a-g......
  • [LeetCode] 149. Max Points on a Line
    Givenanarrayof points where points[i]=[xi,yi] representsapointonthe X-Y plane,return themaximumnumberofpointsthatlieonthesamestraig......
  • JavaScript学习笔记—数组方法slice和splice
    (1)slice()方法定义:从已有的数组返回选定的元素语法:arrayObject.slice(start,end)start:必选。截取开始位置的索引,包含开始索引end:可选。截取结束位置的索引,不包含结......