The general idea is as follows:
Given a sequence, define two pointers left and right, and define the measurement index F before the interval [left,right], such as interval sum, product and others according to the meaning of the question. At the beginning, left=right=0, calculate the index F. left remains unchanged first, right moves to the right, and the value of F is updated. When f meets certain conditions, left moves to the right, which is equivalent to that the interval becomes smaller, and the value of F is updated. If f always meets the meaning of the question, left always moves to the right. If f does not meet the meaning of the question, left remains unchanged and continues to move the right position. In this way, it is equivalent to a sliding window traversing the whole sequence. In the whole process, when the interval [left,right] is found, the process can be recorded and the extreme value can be finally obtained.
Let's have some exercises
/** *Given an array containing n positive integers and a positive integer target. * *Find out the continuous subarray [numsl, numsl + 1,..., numsr-1, numsr] with the smallest length satisfying its sum ≥ target in the array, *And returns its length. If there is no eligible subarray, 0 is returned. * * */
public int minSubArrayLen(int target, int[] nums) { int left = 0; int right = 0; int sum = 0; int min = Integer.MAX_VALUE; // If the sum is less than target, 0 is returned directly int total = Arrays.stream(nums).sum(); if (total < target) return 0; // Double pointer right pointer keeps exploring to the right to find the qualified position // At this point, the left pointer attempts to search for a larger position to the right for (right=0; right<nums.length; right++) { sum = sum + nums[right]; while (sum >= target) { min = Math.min(min, right-left+1); sum = sum - nums[left]; left++; } } return min; }
/** *Given a positive integer array nums and integer k, please find out the number of consecutive sub arrays in the array whose product is less than k. * */
public int numSubarrayProductLessThanK(int[] nums, int k) { int left = 0; int right = 0; int acc = 1; int cnt = 0; for (right=0; right<nums.length; right++) { acc = acc * nums[right]; while (acc >= k && left <= right) { acc = acc / nums[left]; left++; } if (left <= right) { cnt = cnt + (right - left + 1); } } return cnt; }
/** *Given a string s, please find the length of the longest consecutive substring that does not contain duplicate characters. *s consists of English letters, numbers, symbols and spaces * */
public int lengthOfLongestSubstring(String s) { int max = 0; Map<Character, Integer> map = new HashMap<>(); int left = 0; int right = 0; for ( ; right < s.length(); right++) { map.put(s.charAt(right), map.getOrDefault(s.charAt(right), 0) + 1); while (!allLessThanOne(map) && left <= right) { map.put(s.charAt(left), map.getOrDefault(s.charAt(left), 0) - 1); left++; } max = Math.max(max, right - left + 1); } return max; } private boolean allLessThanOne(Map<Character, Integer> map) { return map.values().stream().filter(num -> num > 1).count() == 0; }
/** *Give two strings s and t. Returns the shortest substring of all characters containing T in s *If there is no qualified substring in s, the empty string '' is returned *If there are multiple qualified substrings in s, any one is returned *Note: for repeated characters in T, the number of characters in the substring we are looking for must not be less than the number of characters in t *s and t consist of English letters * */
public String minWindow(String s, String t) { if (s.length() < t.length()) return ""; Map<Character, Integer> map = new HashMap<>(); for (char ch: t.toCharArray()) { map.put(ch, map.getOrDefault(ch, 0) + 1); } int left = 0; int right = 0; int minLength = Integer.MAX_VALUE; int minLeft = 0, minRight = 0; for ( ; right < s.length(); right++) { map.put(s.charAt(right), map.getOrDefault(s.charAt(right), 0) - 1); while (allLessEqualThanOne(map) && left <= right) { if ((right-left) < minLength) { minLeft = left; minRight = right; minLength = minRight - minLeft; } map.put(s.charAt(left), map.getOrDefault(s.charAt(left), 0) + 1); left++; } } return minLength == Integer.MAX_VALUE ? "" : s.substring(minLeft, minRight + 1); } private boolean allLessEqualThanOne(Map<Character, Integer> map) { return map.values().stream().filter(num -> num >= 1).count() == 0; }