【LeetCode】209. 长度最小的子数组
209. 长度最小的子数组
知识点:数组;前缀和;二分法;双指针;滑动窗口
题目描述
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
示例
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。
输入:target = 4, nums = [1,4,4]
输出:1
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0
解法一:暴力法
使用两层for循环遍历;
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int ans = Integer.MAX_VALUE;
for(int i = 0; i < nums.length; i++){
int sum = 0;
for(int j = i; j < nums.length; j++){
sum += nums[j];
if(sum >= target){
ans = Math.min(ans, j-i+1);
break;
}
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}
时间复杂度:0(N^2);
解法二:前缀和+二分法
这道题一看连续子数组触发了前缀和,前缀和就是用来解决连续子数组问题的,所以可以先统计到达每个的前缀和,仍然是为了方便,创建长度是n+1的数组,第一个位置放0,这样最后输出子数组长度的时候不用再去+1了,直接j-i就可以了。
前缀和之后,要想寻找子数组和大于target,就是找sum[i]-sum[j] >= target, 仍然需要遍历两遍,但是前缀和数组有一个重要的特点,就是是递增的(因为只有正数),所以这时候可以用二分搜索,将复杂度降低到O(logN),我们就是想找大于等于sum[i]+target的值.
在java中Arrays类有可以直接调用的Arrays.binarySearch(数组,目标值);如果能找到,就返回找到值的下标,如果没找到就返回一个负数,这个负数取反之后就是查找的值应该在原数组中的位置。
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int n = nums.length;
int ans = Integer.MAX_VALUE;
int[] prenum = new int[n+1];
for(int i = 1; i <= n; i++){
prenum[i] = prenum[i-1] + nums[i-1];
}
for(int i = 0; i < n; i++){
int t = prenum[i] + target;
int index = Arrays.binarySearch(prenum, t);
if(index < 0) index = ~index; //负数的话取反是其应该在元素中的位置;其实也就是第一个比它大的值的元素;
if(index <= n){
ans = Math.min(ans, index-i);
}
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}
时间复杂度:0(NlogN);
解法三:滑动窗口
滑动窗口其实就是双指针的一种,只不过在移动过程中像是一个窗口在移动,所以称作滑动窗口,这是解决连续数组中一个很常见的思路;
可以定义两个指针start和end(分别表示窗口的开始和结束),end从头到尾去遍历数组,当移动出去之后遍历结束。在过程中,将nums[end]不断的加到sum上,如果sum>= target, 那就更新数组的最小长度,然后将nums[stat]在sum中减去,start前移,直到sum< target后,end再移;
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int ans = Integer.MAX_VALUE;
int start = 0, end = 0;
int sum = 0;
while(end < nums.length){
sum += nums[end];
while(sum >= target){
ans = Math.min(ans, end-start+1);
sum -= nums[start]; //超过之后把前面的减去,窗口移动;
start++;
}
end++;
}
return ans == Integer.MAX_VALUE ? 0 : ans;
}
}
时间复杂度:0(NlogN);
体会
连续子数组+和 --> 前缀和
相关链接
【LeetCode】209. 长度最小的子数组的更多相关文章
- Java实现 LeetCode 209 长度最小的子数组
209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 0. 示例: 输入: s = ...
- Leetcode 209.长度最小的子数组 By Python
给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 0. 示例: 输入: s = 7, nums = [2, ...
- LeetCode 209. 长度最小的子数组(Minimum Size Subarray Sum)
题目描述 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 0. 示例: 输入: s = 7, nums ...
- LeetCode:长度最小的子数组【209】
LeetCode:长度最小的子数组[209] 题目描述 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 ...
- 领扣-209 长度最小的子数组 Minimum Size Subarray Sum MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 代码随想录第二天| 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II
2022/09/22 第二天 第一题 这题我就直接平方后排序了,很无脑但很快乐啊(官方题解是双指针 第二题 滑动窗口的问题,本来我也是直接暴力求解发现在leetCode上超时,看了官方题解,也是第一次 ...
- **209. Minimum Size Subarray Sum 长度最小的子数组
1. 题目描述 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 0. 示例: 输入: s = 7, nu ...
- LeetCode 长度最小的子数组
题目: 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组,并返回其长度.如果不存在符合条件的连续子数组,返回 0. 思路: 非常明显用滑动窗口处 ...
- leetcode209. 长度最小的子数组
双指针滑动窗口解法,时间复杂度O(N). 滑动窗口,想象一下,在一个坐标上存在两个指针begin 和i ,begin 代表滑窗的左边框,i代表滑窗的右边框.两者通过分别向右滑动,前者能使窗口之间的和减 ...
随机推荐
- JDK并发包一
JDK并发包一 同步控制是并发程序必不可少的重要手段,synchronized是一种最简单的控制方法.但JDK提供了更加强大的方法----重入锁 重入锁 重入锁使用java.util.concurre ...
- 解决mac中adb: command not found
在Mac系统中,很多时候第一次在Android SDK中使用adb的时候.无法使用.会提示-bash: abd: command not found. 造成此类现象的原因是:未配置Android的环境 ...
- sql循环说明
while循环:主要是判断,不能使用表中的ID,临时表是ID自增的,通过自增ID可以查出表ID(语法简单,需要配合其他代码操作表ID)游标循环:可以使用表中的ID ,进行修改等操作(语法难一点,核心代 ...
- 什么是TCP和UDP?
1.什么是IP和TCP? Internet协议(IP)是Internet的地址系统,具有将数据包从源设备传递到目标设备的核心功能.IP是建立网络连接的主要方式,奠定了Internet的基础.IP不负责 ...
- 50、django工程(ajax)
50.1.ajax介绍: 1.ajax是在不跳转当前url地址的情况偷偷的往后台发送数据做增删改数据的操作,如果成功返回结果刷新当前页面,失败则提醒, 使用 id 或 name 属性. 2.模态对话框 ...
- SpringBoot拦截器及源码分析
1.拦截器是什么 java里的拦截器(Interceptor)是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止 ...
- PO,VO,BO,POJO,DAO的区别
基本概念 PO:persistant object (持久化对象),可以看成是与数据库中的表相映射的java对象.最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合.PO中应该不 ...
- 单选按钮(radio)的取值和点击事件
笔记走一波:获取单选按钮(radio)的选中值,以及它的点击事件的实现 首先要引入Jquery <script type="text/javascript" src=&quo ...
- 63. Unique Paths II 动态规划
description: https://leetcode.com/problems/unique-paths/ 机器人从一堆方格的左上角走到右下角,只能往右或者往下走 ,问有几种走法,这个加了难度, ...
- netcore3.1 + vue (前后端分离)生成PDF(多pdf合并)返回前端打印
1.使用Adobe Acrobat XI Pro编辑pdf模板 2.公共类代码 3.service层调用 4.Controller层 5.前端(Vue) 因为print.js不支持宋体,所以打算用后台 ...