首页 > 基础资料 博客日记
长度最小的子数组(Java详解)
2023-12-27 21:30:31基础资料围观246次
目录
题目描述
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其和 ≥ target
的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例:
输入:target = 7, nums = [2,3,1,2,4,3] 输出:2
输入:target = 4, nums = [1,4,4] 输出:1
题解
思路分析
题目要求我们找到和 >= target 的 最小 且 连续 的子数组,我们很容易想到暴力枚举的方法,即访问数组的每一个元素i,并将i作为第一个元素,向后寻找
暴力枚举代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int count = 0;
for(int i = 0; i < nums.length; i++){
int sum = 0;
//向后遍历找到以nums[i]为起始元素的最小数组
for(int j = i; j < nums.length;j++){
sum += nums[j];
if(sum >= target){
//更新目标值 由于count的初始值为0,因此需要更新初始值,
//否则最小值恒为0
if(count > j-i+1 || count == 0){
count = j-i+1;
}
break;
}
}
}
//若count未被更新,则返回0,即没有子数组的和大于target,
//若count被跟新,则返回最小的子数组长度
return count;
}
}
此时我们通过遍历访问了数组的每个元素,在访问每个元素时,以该元素为起始元素,并向后寻找其最小长度的子数组,因此时间复制度为O()
而,题目所给的数组中所有元素均是正整数,因此每加上一个元素,子数组的和 sum 增加,通过这个特性,我们可以想到使用滑动窗口来解决这个问题
什么是滑动窗口?
滑动窗口是一种基于双指针的思想,两个指针指向的元素之间形成了一个窗口
因此滑动窗口是通过两个指针来维护的,那么如何移动这两个指针,是使用滑动窗口解决问题的关键
初始时,两个指针都指向0下标位置
遍历元素,若条件不满足,则将right指针向右移动,直到条件满足为止
当条件满足时,则保持右指针不变,开始移动左指针 left
在向窗口中添加新元素或从窗口中删除旧元素时,可能会更新一些与窗口范围有关的数据(例如,本题就需要更新最小子数组的长度)
如何使用滑动窗口解决本题?
(1)我们定义两个指针left right,并让其都指向数组首元素
(2)此时窗口内只有 2 这一个元素,不满足和 sum >= target,因此将right向右移动,将新的元素加入窗口中,并判断此时子数组的和 sum 是否大于等于target,若满足,则不再移动right
(3)在sum >= target时,首先判断最小的子数组长度是否需要更新,并保持right不变,向右移动左指针left,删除旧的元素,直到sum < target
(4)循环(2)(3),直到right遍历完数组
为什么可以使用滑动窗口解决本题?
因为我们要找的子数组是连续的,且数组中的元素都为正整数,即子数组中增加一个元素,子数组中的元素和sum增加,从窗口中删除一个元素,sum减小,因此我们可以通过改变子数组的两端元素来更新数组,因此可以使用滑动窗口来解决本题
由于左右指针都只遍历了一遍数组,因此时间复杂度为O(N)
滑动窗口代码
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int left = 0;
int right = 0;
int sum = nums[0];
int len = nums.length;
int count = 0;
while(left <= right && right < len){
//小于目标值,向右移动右指针right
while(left <= right && right < len && sum < target){
right++;
if(right == len){
break;
}
sum += nums[right];
}
//大于等于目标值
while(left <= right && sum >= target){
//更新目标值 由于count的初始值为0,因此需要更新初始值,否则最小值恒为0
if((right - left) < count || count == 0){
count = right - left + 1;
}
//左边值出窗口,left向右移动
sum -= nums[left];
left++;
}
}
//若count未被更新,则返回0,即没有子数组的和大于target,
//若count被跟新,则返回最小的子数组长度
return count;
}
}
题目来自:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:jacktools123@163.com进行投诉反馈,一经查实,立即删除!
标签: