76. 最小覆盖子串 - 力扣(LeetCode)
不断移动右指针,如果指针指向的元素是目标元素,则存入哈希表中。
检查是否满足要求,如果满足,就移动左指针,并且把左指针遍历的元素移除哈希表。
class Solution {Map<Character,Integer> ori = new HashMap<>();Map<Character,Integer> cnt = new HashMap<>();public String minWindow(String s, String t) {int tlen = t.length();//生成目标元素的哈希表for(int i = 0; i < tlen; i++){char c = t.charAt(i);ori.put(c, ori.getOrDefault(c,0) + 1); }int l = 0, r = -1;int slen = s.length();int minLen = Integer.MAX_VALUE, ansL = -1, ansR = -1;while(r < slen){r++;if(r < slen && ori.containsKey(s.charAt(r))){char relem = s.charAt(r);cnt.put(relem, cnt.getOrDefault(relem,0) + 1);}while(check() && l <=r){if(r-l+1 < minLen){minLen = r-l+1;ansL = l;ansR = r;}char lelem = s.charAt(l);if(ori.containsKey(lelem)){cnt.put(lelem,cnt.getOrDefault(lelem, 0) - 1);}l++;}} return ansL == -1? "":s.substring(ansL,ansR + 1);}public boolean check(){Iterator iter = ori.entrySet().iterator();while(iter.hasNext()){Map.Entry entry = (Map.Entry)iter.next();Character key = (Character)entry.getKey();Integer val = (Integer)entry.getValue();if(cnt.getOrDefault(key,0) < val){return false;}}return true;}
}
//被子收纳
3. 无重复字符的最长子串 - 力扣(LeetCode)
右指针不断向右移动,用哈希表记录已经覆盖的字符,如果遇到的下一个字符x是哈希表中包含的,则将左指针移动到上次出现该字符x的位置,并且将哈希表中左指针遍历的元素都删掉。
class Solution {public int lengthOfLongestSubstring(String s) {Map<Character,Integer> hm = new HashMap<>();int r = -1;int slen = s.length();int maxLen = 0;for(int i = 0; i < slen; i++){if(i != 0){//这里不能删除i指向的字符,因为i是更新过后的,要删除旧的hm.remove(s.charAt(i - 1));}//这部分是为了判断下一个字符是否当前哈希表已经包含了,如果已经包含,则逐个删除字符,直到哈希表不含下一个字符为止。while(r + 1 < slen && hm.containsKey(s.charAt(r + 1)) != true){hm.put(s.charAt(r + 1) , 1);r++;}//当右指针移不动的时候,更新长度。maxLen = Math.max(maxLen, r - i + 1);}return maxLen;}
}
11. 盛最多水的容器 - 力扣(LeetCode)
当长只能缩小的时候,高必须增大,才能让面积增大。因此每次都移动比较短的高,试图让他增大。
class Solution {public int maxArea(int[] height) {int l = 0, r = height.length - 1;int res = 0;while( l < r){int area = (r-l)* Math.min(height[l],height[r]);res = Math.max(area,res);if(height[l] < height[r]){int cur = height[l];while(l < r && height[l] <= cur) l++;}else{int cur = height[r];while(l < r && height[r] <= cur) r--;}}return res;}
}
LCR 007. 三数之和 - 力扣(LeetCode)
要理解左右指针同时往右边移动是一定是递增的,同时往左边一定是递减的。
遍历每个元素,然后给每个元素赋予左右指针,让他们从左右不断向内靠拢,如果三数之和大于0,就把右指针左移。反之亦然。如果相等同时移动左右指针向内,如果仅移动一侧向内,仍然保持相等,那么结果一定是重复的,当然同时向内也有可能重复,因此需要判断两个指针的 下一位指向元素是否和当前指向相等。
class Solution {public List<List<Integer>> threeSum(int[] nums) {Arrays.sort(nums);List<List<Integer>> res = new LinkedList<>();for(int i = 0; i < nums.length - 2; i++){if(nums[i] > 0 ) return res;if(i > 0 && nums[i] == nums[i-1]) continue;int left = i + 1;int right = nums.length - 1;while(i >= 0 && left < right){ if(nums[i] + nums[left] + nums[right] == 0){List<Integer> tmp = new LinkedList<>();tmp.add(nums[i]);tmp.add(nums[left]);tmp.add(nums[right]);res.add(tmp);left++;right--;while(left < right && nums[left-1] == nums[left] && nums[right] == nums[right+1]){left++;right--;}}else if(nums[i] + nums[left] + nums[right] > 0){right--;}else if(nums[i] + nums[left] + nums[right] < 0){left++;}}}return res;}
}