力扣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( ...
随机推荐
- 海词 dict.cn 有 词义饼状分布图 和 词性饼状分布图 - 词典推荐
海词 dict.cn 有 词义饼状分布图 和 词性饼状分布图 http://dict.cn/like
- private priv 私人 pri=prim first v=self 自己第一
private priv 私人 pri=prim first v=self 自己第一 private v自己-私人的 pri 来自PIE*per,向前,穿过 pri = pre 向前(这么理解也说的过 ...
- history = his + story 男性史 = 历史 学单词
history = his + story 男性史 = 历史 早先还有 herstory 由于女性地位底下,就由 history 代表历史了. 然后 history 由拉丁文过来 story 从法语过 ...
- 基于Python的 如何检查字符串输入是否为数字
一 概念 这种有很多常用的方法,这里只介绍一种常用的方法是使用正则表达式来匹配数字的模式.通过定义一个匹配数字的正则表达式,然后使用re模块中的search()方法来进行匹配. 二 例子: 下面是一个 ...
- electron 中如何安装或更新 vuejs-devtool 最新稳定版
手上正在开发的项目是vue3.0 通过添加 vue-cli-plugin-electron-builder 插件生成 electron 项目,项目在开发过程中发现 beta版的 vuejs-devto ...
- LoggerMessageAttribute 高性能的日志记录
.NET 6 引入了 LoggerMessageAttribute 类型. 使用时,它会以source-generators的方式生成高性能的日志记录 API. source-generators可在 ...
- 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 ...
- 3、Azure Devops之Azure Repos篇
1.什么是Azure Repos Azure Repos,就是我们常说的代码仓库,相当于gitee,github,git,svn工具.主要是提供给开发人员使用的,管理.查看代码的部件.通过Files. ...
- Lambda Web Browser使用教程
Lambda web browser是一个功能强大的UE内置浏览器插件, 允许用户在编辑器模式和运行时启动一个浏览器窗口, 对于一些采用传统BS架构的项目而言, 控制页面都放在前段, 若想要将控制页面 ...
- 记录--源码视角,Vue3为什么推荐使用ref而不是reactive
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 ref 和 reactive 是 Vue3 中实现响应式数据的核心 API.ref 用于包装基本数据类型,而 reactive 用于处理对 ...