本题使用滑动窗口思想:
所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。
在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。
在本题中实现滑动窗口,主要确定如下三点:
- 窗口内是什么?
- 如何移动窗口的起始位置?
- 如何移动窗口的结束位置?
窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。
窗口的起始位置如何移动:如果当前窗口的值大于等于s了,窗口就要向前移动了(也就是该缩小了)。
窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。
package Linklist; public class TheSmallestLengthSubarray { public static void main(String[] args) { int s=10; int arr[]={1,2,3,4,1,2,3,4}; int x=minSubArrayLen(s,arr); System.out.println(x); } public static int minSubArrayLen(int s, int[] nums) { int left = 0; int sum = 0; int result = Integer.MAX_VALUE; //result:用于记录最短子数组的长度,初始化为 Integer.MAX_VALUE。这是为了确保任何有效的子数组长度都会小于这个初始值,从而能够正确地更新 result。 //Integer.MAX_VALUE 是 Java 中 int 类型能够表示的最大值(2^31 - 1,即 2,147,483,647)。 //在这个算法中,Integer.MAX_VALUE 被用作 result 的初始值。这样做的目的是确保在找到第一个满足条件的子数组之前,任何有效的子数组长度都会小于这个初始值。 for (int right = 0; right < nums.length; right++) { sum += nums[right]; while (sum >= s) { result = Math.min(result, right - left + 1); sum -= nums[left++]; } } // 使用 while 循环检查当前窗口内的元素和是否大于等于目标值 s。 // 如果是,则更新 result 为当前窗口长度(right - left + 1)和 result 中的较小值。 // 然后,通过移动左边界(left++)和从 sum 中减去 nums[left] 的值来缩小窗口,尝试找到更短的满足条件的子数组。 // 如果遍历完整个数组后,result 仍然是 Integer.MAX_VALUE,说明没有找到任何满足条件的子数组,此时返回 0(表示不存在这样的子数组)。 return result == Integer.MAX_VALUE ? 0 : result; } }