滑动窗口 3. 无重复字符的最长子串
参见《剑指Offer》最长不含重复字符的子字符串 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Solution { public int lengthOfLongestSubstring (String s) { HashMap<Character, Integer> map = new HashMap<>(); int l = 0 , r = 0 , res = 0 ; while (r<s.length()) { char c = s.charAt(r); if (map.containsKey(c)) { l = Math.max(l, map.get(c)+1 ); } res = Math.max(res, r-l+1 ); map.put(c, r); r++; } return res; } }
76. 最小覆盖子串
使用滑动窗口模拟最小覆盖子串,用数组记录所需的字符数量和窗口中的字符数量。首先向右扩张窗口边界直到滑动窗口包含全部所需的字符,然后不断向右缩小左边界直到窗口中不满足全部所需字符,同时不断更新最小覆盖子串的长度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { public String minWindow (String s, String t) { int l = -1 , r = -1 , minLen = Integer.MAX_VALUE; int [] need = new int [128 ]; int count = 0 ; for (char c: t.toCharArray()) { need[c]++; count++; } int [] window = new int [128 ]; int i = 0 , j = 0 ; while (j<s.length()) { char rc = s.charAt(j); window[rc]++; if (window[rc]<=need[rc]) count--; while (count==0 ) { if (minLen>j-i+1 ) { minLen = j-i+1 ; r = j; l = i; } char lc = s.charAt(i); window[lc]--; i++; if (window[lc]<need[lc]) count++; } j++; } return l>=0 ? s.substring(l, r+1 ): "" ; } }
239. 滑动窗口最大值
参见《剑指Offer》滑动窗口的最大值 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public int [] maxSlidingWindow(int [] nums, int k) { if (nums.length==0 ) return new int []{}; LinkedList<Integer> queue = new LinkedList<>(); for (int i=0 ; i<k; i++) { while (!queue.isEmpty() && queue.peekLast()<nums[i]) { queue.pollLast(); } queue.offer(nums[i]); } int [] res = new int [nums.length-k+1 ]; res[0 ] = queue.peek(); for (int i=k; i<nums.length; i++) { if (nums[i-k]==queue.peekFirst()) queue.pollFirst(); while (!queue.isEmpty() && queue.peekLast()<nums[i]) { queue.pollLast(); } queue.offer(nums[i]); res[i-k+1 ] = queue.peekFirst(); } return res; } }
438. 找到字符串中所有字母异位词
此题与76题相似,不同的是只记录窗口中所需字符的数量,并且只当窗口大小与模式字符串相等时才判断是否是字母异位词,然后缩小左边界。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 class Solution { public List<Integer> findAnagrams (String s, String p) { int [] need = new int [128 ]; for (char c: p.toCharArray()) { need[c]++; } int count = 0 ; int [] window = new int [128 ]; int left = 0 , right = 0 ; ArrayList<Integer> res = new ArrayList<>(); while (right < s.length()) { char rc = s.charAt(right); if (need[rc]>0 ) { window[rc]++; if (window[rc]<=need[rc]) { count++; } } right++; while (count==p.length()) { if (right-left==p.length()) { res.add(left); } char lc = s.charAt(left); if (need[lc]>0 ) { window[lc]--; if (window[lc]<need[lc]) { count--; } } left++; } } return res; } }