import java.util.*; /** * NC343 和大于等于K的最短子数组 * @author d3y1 */ public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型ArrayList * @param k int整型 * @return int整型 */ public int shortestSubarray (ArrayList<Integer> nums, int k) { // return solution1(nums, k); // return solution2(nums, k); return solution3(nums, k); } /** * 二分 * @param nums 正整数数组! * @param k * @return */ private int solution1(ArrayList<Integer> nums, int k){ int n = nums.size(); // 前缀和 long[] preSum = new long[n+1]; for(int i=1; i<=n; i++){ preSum[i] = preSum[i-1]+nums.get(i-1); } int result = Integer.MAX_VALUE; int left = 1; int right = n; int mid; // 二分 while(left <= right){ mid = left+(right-left)/2; if(check(preSum, k, mid)){ result = Math.min(result, mid); right = mid-1; }else{ left = mid+1; } } return result==Integer.MAX_VALUE?-1:result; } /** * 校验gap大小窗口是否满足条件(preSum[j]-preSum[i] >= k) * @param preSum * @param target * @param gap * @return */ private boolean check(long[] preSum, int target, int gap){ for(int i=0,j=i+gap; j<preSum.length; i++,j++){ if(preSum[j]-preSum[i] >= target){ return true; } } return false; } /** * 双指针: 滑动窗口 * @param nums 正整数数组! * @param k * @return */ private int solution2(ArrayList<Integer> nums, int k){ int n = nums.size(); int result = Integer.MAX_VALUE; int left=0; int right=0; int sum = 0; int numL,numR; while(right < n){ numR = nums.get(right++); if(numR >= k){ return 1; } sum += numR; while(left<=right && sum>=k){ result = Math.min(result, right-left); numL = nums.get(left++); sum -= numL; } } return result==Integer.MAX_VALUE?-1:result; } /** * 单调栈: 单调增 * @param nums 整数数组! * @param k * @return */ private int solution3(ArrayList<Integer> nums, int k){ int n = nums.size(); // 前缀和 long[] preSum = new long[n+1]; for(int i=1; i<=n; i++){ preSum[i] = preSum[i-1]+nums.get(i-1); } int result = Integer.MAX_VALUE; Deque<Integer> queue = new ArrayDeque<>(); for(int i=0; i<=n; i++){ long curSum = preSum[i]; // 判断 是否满足条件(>=k) while(!queue.isEmpty() && curSum-preSum[queue.peekFirst()]>=k){ result = Math.min(result, i-queue.pollFirst()); } // 单调栈(单调增) while(!queue.isEmpty() && preSum[queue.peekLast()]>=curSum){ queue.pollLast(); } queue.offerLast(i); } return result==Integer.MAX_VALUE?-1:result; } }