力扣209(java&python)-长度最小的子数组(中等)
题目:
给定一个含有 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)-长度最小的子数组(中等)的更多相关文章
- 代码随想录训练营day 2 |977有序数组的平方 209.长度最小的子数组 (C++)
977.有序数组的平方 题目链接:977.有序数组的平方 题目描述:给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序. 例子如下: 输入 ...
- 双指针之滑动窗口(长度最小的子数组 和 和为s的连续正数序列)
双指针之滑动窗口 (长度最小的子数组:和为s的连续正数序列) 1, 什么时候使用? (与子数组/字符串 有关的题目)~如果给了某个具体值的target,即用滑动窗口 不然就双指针(一般做法,左边< ...
- 209. 长度最小的子数组--LeetCode
来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/minimum-size-subarray-sum 著作权归领扣网络所有.商业转载请联系官方授权,非商业 ...
- 有序数组的平方&长度最小的子数组&螺旋矩阵Ⅱ
一.有序数组的平方 977.有序数组的平方 leetcode链接 1.方法概述 双"指针"解法:因为数组本来是有序的,平方后可能出现的两端大数值大的情况.所以从数组两端开始遍历,谁 ...
- [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 ...
- 力扣1052. 爱生气的书店老板-C语言实现-中等难度
题目 传送门 文本 今天,书店老板有一家店打算试营业 customers.length 分钟.每分钟都有一些顾客(customers[i])会进入书店,所有这些顾客都会在那一分钟结束后离开. 在某些时 ...
- [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 ...
- Java实现 LeetCode 795 区间子数组个数 (暴力分析)
795. 区间子数组个数 给定一个元素都是正整数的数组A ,正整数 L 以及 R (L <= R). 求连续.非空且其中最大元素满足大于等于L 小于等于R的子数组个数. 例如 : 输入: A = ...
- 力扣(LeetCode)453. 最小移动次数使数组元素相等
给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数.每次移动可以使 n - 1 个元素增加 1. 示例: 输入: [1,2,3] 输出: 3 解释: 只需要3次移动(注意每次移动 ...
- [Swift-2019力扣杯春季初赛]3. 最小化舍入误差以满足目标
给定一系列价格 [p1,p2...,pn] 和一个目标 target,将每个价格 pi 舍入为 Roundi(pi) 以使得舍入数组 [Round1(p1),Round2(p2)...,Roundn( ...
随机推荐
- [TM4] TM4C123G Keil5 新建工程指南
[TM4] TM4C123G Keil5 新建工程指南 keil新建工程,选择TM4C123GH6PM芯片,然后在CMSIS勾选CORE,DEVICE勾选Startup(如图),来到新工程界面 在So ...
- Android网络收集和ping封装库
目录介绍 01.基础介绍 02.stetho大概流程 03.Android中应用 04.如何使用 05.案例截图如下 06.网络请求接口信息 07.如何使用ping 01.基础介绍 该工具作用 诸葛书 ...
- Dialog源码分析
目录介绍 1.简单用法 2.AlertDialog源码分析 2.1 AlertDialog.Builder的构造方法 2.2 通过AlertDialog.Builder对象设置属性 2.3 build ...
- 恶意软件开发(四)通过查找进程名进行DLL注入
通过进程名查找PID 当我们编写注入器的时候,肯定是希望直接通过进程名进行注入,而不是像上一篇笔记一样通过手动输入PID进行查找. 通过进程名查找PID的步骤如下: (1)创建系统中所有进程的快照 ( ...
- 说说你对keep-alive的理解是什么?
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 一.Keep-alive 是什么 keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM ke ...
- 记录--关于无感刷新Token,我是这样子做的
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 什么是JWT JWT是全称是JSON WEB TOKEN,是一个开放标准,用于将各方数据信息作为JSON格式进行对象传递,可以对数据进行可 ...
- KingbaseES V8R6 运维案例 --flashback drop table
一.KingbaseES V8R6 flashback drop table介绍 使用FLASHBACK删除和恢复表 删除表时,数据库不会立即删除与该表关联的空间.数据库重命名表,并将其和任何关联的对 ...
- archlinux调整分区及ext4文件系统大小
参照 https://wiki.archlinuxcn.org/wiki/Parted 1.防止数据丢失 有重要数据的话先备份,防止系统崩了数据没了 可以的话先在虚拟机练习一下 2.注意点 修改分区的 ...
- MySQL检索和过滤数据
注意 多条SQL语句必须以分号(:)分隔: SQL语句不区分大小写: 在处理SQL语句时,其中所有空格都被忽略: 当选择多个列是,一定要在列名之间加上逗号,但最后一个列名后不加. SELECT语句 检 ...
- #整体二分,树状数组#洛谷 3332 [ZJOI2013]K大数查询
题目 分析 虽然树套树也可以做,这里考虑整体二分, 对于二分的答案\(mid\),1操作实际上就是如果\(c>mid\)就给区间整体加1, 2操作即询问区间和是否超过\(k\),如果超过\(k\ ...