题目:

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:

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

输入:target = 4, nums = [1,4,4]
输出:1
示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105

进阶:

如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-size-subarray-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

一、【前缀和+二分查找】

前缀和:sum[i]表示从nums[0]到nums[i-1]的元素和。本题中说明了每个元素都为正,所以前缀和一定是递增的。

  • 首先预处理出前缀和数组sum,前缀和数组下标从1开始,sum[i] = sum[i - 1] + nums[i - 1];
  • 假设s对应的前缀和为:s = sum[i+1]=sum[i] + nums[i],将nums[i]视为结果数组的右端点,现在问题转换为找结果数组的左端点,已知s和target,题目要求是要找到大于等于target的最小数组长度,于是可以转换成在前缀和数组下标[0,i]中内找到满足小于等于d = s - target的最大下标,这个最大下标就是结果数组的左端点。

注意:

代码中更新最短长度用的:i - left,为什么没有写成 i - left+ 1?

因为前缀和下标从1开始的,而left是从下标0开始的。故相减下来就是数组的长度。

 java代码:

 1 class Solution {
2 public int minSubArrayLen(int target, int[] nums) {
3 int n = nums.length, ans = Integer.MAX_VALUE;
4 int[] sum = new int[n + 1];
5 //计算前缀和
6 for (int i = 1; i <= n; i++){
7 sum[i] = sum[i - 1] + nums[i - 1];
8 }
9 for (int i = 1; i <= n; i++){
10 int s = sum[i], d = s - target;
11 int left = 0, right = i;
12 while (left < right){
13 int mid = left + (right - left + 1) / 2;
14 //不够d,需要往右移
15 if (sum[mid] <= d){
16 left = mid;
17 }else{
18 //超过了d,往左移
19 right = mid - 1;
20 }
21 }
22 //循环结束:left == right,找到小于等于d的最大下标,更新最小长度
23 if (sum[left] <= d){
24 ans = Math.min(ans, i - left);
25 }
26 }
27 return ans == Integer.MAX_VALUE ? 0 : ans;
28 }
29 }

 二、【滑动窗口】--双指针

滑动窗口需要考虑的三点:

1.窗口内是什么?

2.怎么移动窗口的起始位置?

3.怎么移动窗口的结束位置?

然后本题就是:

1.窗口内就是 满足其和 ≥ s 的长度最小的 连续 子数组。

2.窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

3.窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

关键部分图解:

来源:代码随想录

复杂度:

主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。

java代码:

 1 class Solution {
2 public int minSubArrayLen(int target, int[] nums) {
3 int n = nums.length, ans = Integer.MAX_VALUE;
4 int left = 0, sublen = 0, sum = 0;
5 for (int right = 0; right < n; right++){
6 sum += nums[right];
7 while (sum >= target){
8 //获取当前数组长度
9 sublen = right - left + 1;
10 ans = Math.min(ans, sublen);
11 sum -= nums[left++];
12 }
13 }
14 return ans == Integer.MAX_VALUE ? 0 : ans;
15 }
16 }

 python3代码:

 1 class Solution:
2 def minSubArrayLen(self, target: int, nums: List[int]) -> int:
3 left, ans, sum, sublen = 0, float("inf"), 0, 0
4 for right in range(len(nums)):
5 sum += nums[right]
6 while sum >= target:
7 sublen = right - left + 1
8 ans = min(sublen, ans)
9 sum -= nums[left]
10 left += 1
11 return 0 if ans == float("inf") else ans

力扣209(java&python)-长度最小的子数组(中等)的更多相关文章

  1. 代码随想录训练营day 2 |977有序数组的平方 209.长度最小的子数组 (C++)

    977.有序数组的平方 题目链接:977.有序数组的平方 题目描述:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序. 例子如下: 输入 ...

  2. 双指针之滑动窗口(长度最小的子数组 和 和为s的连续正数序列)

    双指针之滑动窗口 (长度最小的子数组:和为s的连续正数序列) 1, 什么时候使用? (与子数组/字符串 有关的题目)~如果给了某个具体值的target,即用滑动窗口 不然就双指针(一般做法,左边< ...

  3. 209. 长度最小的子数组--LeetCode

    来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/minimum-size-subarray-sum 著作权归领扣网络所有.商业转载请联系官方授权,非商业 ...

  4. 有序数组的平方&长度最小的子数组&螺旋矩阵Ⅱ

    一.有序数组的平方 977.有序数组的平方 leetcode链接 1.方法概述 双"指针"解法:因为数组本来是有序的,平方后可能出现的两端大数值大的情况.所以从数组两端开始遍历,谁 ...

  5. [Swift]LeetCode209. 长度最小的子数组 | Minimum Size Subarray Sum

    Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...

  6. 力扣1052. 爱生气的书店老板-C语言实现-中等难度

    题目 传送门 文本 今天,书店老板有一家店打算试营业 customers.length 分钟.每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开. 在某些时 ...

  7. [LeetCode] 209. Minimum Size Subarray Sum 最短子数组之和

    Given an array of n positive integers and a positive integer s, find the minimal length of a contigu ...

  8. Java实现 LeetCode 795 区间子数组个数 (暴力分析)

    795. 区间子数组个数 给定一个元素都是正整数的数组A ,正整数 L 以及 R (L <= R). 求连续.非空且其中最大元素满足大于等于L 小于等于R的子数组个数. 例如 : 输入: A = ...

  9. 力扣(LeetCode)453. 最小移动次数使数组元素相等

    给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数.每次移动可以使 n - 1 个元素增加 1. 示例: 输入: [1,2,3] 输出: 3 解释: 只需要3次移动(注意每次移动 ...

  10. [Swift-2019力扣杯春季初赛]3. 最小化舍入误差以满足目标

    给定一系列价格 [p1,p2...,pn] 和一个目标 target,将每个价格 pi 舍入为 Roundi(pi) 以使得舍入数组 [Round1(p1),Round2(p2)...,Roundn( ...

随机推荐

  1. 海词 dict.cn 有 词义饼状分布图 和 词性饼状分布图 - 词典推荐

    海词 dict.cn 有 词义饼状分布图 和 词性饼状分布图 http://dict.cn/like

  2. private priv 私人 pri=prim first v=self 自己第一

    private priv 私人 pri=prim first v=self 自己第一 private v自己-私人的 pri 来自PIE*per,向前,穿过 pri = pre 向前(这么理解也说的过 ...

  3. history = his + story 男性史 = 历史 学单词

    history = his + story 男性史 = 历史 早先还有 herstory 由于女性地位底下,就由 history 代表历史了. 然后 history 由拉丁文过来 story 从法语过 ...

  4. 基于Python的 如何检查字符串输入是否为数字

    一 概念 这种有很多常用的方法,这里只介绍一种常用的方法是使用正则表达式来匹配数字的模式.通过定义一个匹配数字的正则表达式,然后使用re模块中的search()方法来进行匹配. 二 例子: 下面是一个 ...

  5. electron 中如何安装或更新 vuejs-devtool 最新稳定版

    手上正在开发的项目是vue3.0 通过添加 vue-cli-plugin-electron-builder 插件生成 electron 项目,项目在开发过程中发现 beta版的 vuejs-devto ...

  6. LoggerMessageAttribute 高性能的日志记录

    .NET 6 引入了 LoggerMessageAttribute 类型. 使用时,它会以source-generators的方式生成高性能的日志记录 API. source-generators可在 ...

  7. js之实现页面内所有图片旋转

    javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6; y3=.24; x4=300; y4=200; x5=300; y5=200; DI=do ...

  8. 3、Azure Devops之Azure Repos篇

    1.什么是Azure Repos Azure Repos,就是我们常说的代码仓库,相当于gitee,github,git,svn工具.主要是提供给开发人员使用的,管理.查看代码的部件.通过Files. ...

  9. Lambda Web Browser使用教程

    Lambda web browser是一个功能强大的UE内置浏览器插件, 允许用户在编辑器模式和运行时启动一个浏览器窗口, 对于一些采用传统BS架构的项目而言, 控制页面都放在前段, 若想要将控制页面 ...

  10. 记录--源码视角,Vue3为什么推荐使用ref而不是reactive

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 ref 和 reactive 是 Vue3 中实现响应式数据的核心 API.ref 用于包装基本数据类型,而 reactive 用于处理对 ...