本文主要是介绍力扣爆刷第84天之hot100五连刷6-10,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
力扣爆刷第84天之hot100五连刷6-10
文章目录
- 力扣爆刷第84天之hot100五连刷6-10
- 一、15. 三数之和
- 二、42. 接雨水
- 三、3. 无重复字符的最长子串
- 四、438. 找到字符串中所有字母异位词
- 五、560. 和为 K 的子数组
一、15. 三数之和
题目链接:https://leetcode.cn/problems/3sum/description/?envType=study-plan-v2&envId=top-100-liked
思路:三数之和和两数之和类似都是使用双指针进行操作,只不过nums数组内包含重复元素,需要考虑去重的操作,先排序,然后外层一个for内层双指针即可完成遍历,完成去重有两步。
一步: if (i > 0 && nums[i] == nums[i-1]) continue;杜绝相同的nums[i]。
二步:当nums[j]+nums[k]==nums[i]时,务必保证nums[j]和nums[k]不再重复。
while(j < k && nums[j] == nums[j+1]) j++;
while(j < k && nums[k] == nums[k-1]) k--;
j++;
k--;
class Solution {public List<List<Integer>> threeSum(int[] nums) {List<List<Integer>> array = new ArrayList<>();Arrays.sort(nums);int len = nums.length;for(int i = 0; i < len-2; i++) {if (nums[i] > 0) break;if (i > 0 && nums[i] == nums[i-1]) continue;int j = i+1, k = len-1;while(j < k) {int temp = nums[i] + nums[j] + nums[k];if(temp == 0) {List<Integer> list = new ArrayList<>();list.add(nums[i]);list.add(nums[j]);list.add(nums[k]);array.add(list);while(j < k && nums[j] == nums[j+1]) j++;while(j < k && nums[k] == nums[k-1]) k--;j++;k--;}else if(temp < 0) {j++;}else {k--;}}}return array;}
}
二、42. 接雨水
题目链接:https://leetcode.cn/problems/trapping-rain-water/description/?envType=study-plan-v2&envId=top-100-liked
思路:接雨水是典型的单调栈问题,只需要构造出来凹型即可,也就是栈内,自栈底到栈顶是递减的,当遇到大于栈顶的元素时,就弹出栈顶,此时栈顶即为凹槽,然后计算面积即可。
class Solution {public int trap(int[] height) {Deque<Integer> stack = new LinkedList<>();int sum = 0;for(int i = 0; i < height.length; i++) {while(!stack.isEmpty() && height[stack.peek()] < height[i]) {int mid = stack.pop();if(!stack.isEmpty()) {int h = Math.min(height[i], height[stack.peek()]) - height[mid];int w = i - stack.peek() - 1; sum += h * w;}}stack.push(i);}return sum;}
}
三、3. 无重复字符的最长子串
题目链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/description/?envType=study-plan-v2&envId=top-100-liked
思路:如s = “abcabcbb” 长度为3,典型的滑动窗口,使用set维护不重复的子串,每次新加入元素后,更新最大长度,如果遇到重复元素,则开始缩小窗口,直到当前元素不重复,才继续开始扩大窗口。
class Solution {public int lengthOfLongestSubstring(String s) {int max = 0;Set<Character> set = new HashSet<>();int slow = 0;for(int i = 0; i < s.length(); i++) {while(set.contains(s.charAt(i))) {set.remove(s.charAt(slow));slow++;}set.add(s.charAt(i));max = Math.max(max, set.size());}return max;}
}
四、438. 找到字符串中所有字母异位词
题目链接:https://leetcode.cn/problems/find-all-anagrams-in-a-string/description/?envType=study-plan-v2&envId=top-100-liked
思路:一看是异位词基本上就得使用set或map来处理,字符串的长度又巨长,10的4次方,常规遍历自然超时,需要使用双指针去掉一层循环,即使用滑动窗口,维护好字符串窗口,开始时扩大窗口,顺便记录标记值,当窗口达到p字符串长度时,进行判断,看看标记值是否符合,然后缩减窗口,这样一次循环结束。
滑动窗口模板:
/* 滑动窗口算法框架 */
void slidingWindow(String s) {// 用合适的数据结构记录窗口中的数据HashMap<Character, Integer> window = new HashMap<>();int left = 0, right = 0;while (right < s.length()) {// c 是将移入窗口的字符char c = s.charAt(right);window.put(c, window.getOrDefault(c, 0) + 1);// 增大窗口right++;// 进行窗口内数据的一系列更新.../*** debug 输出的位置 ***/// 注意在最终的解法代码中不要 print// 因为 IO 操作很耗时,可能导致超时System.out.printf("window: [%d, %d)\n", left, right);/********************/// 判断左侧窗口是否要收缩while (left < right && window needs shrink) {// d 是将移出窗口的字符char d = s.charAt(left);window.put(d, window.get(d) - 1);// 缩小窗口left++;// 进行窗口内数据的一系列更新...}}
}
题解:
class Solution {public List<Integer> findAnagrams(String s, String p) {List<Integer> list = new ArrayList<>();int sLen = s.length(), pLen = p.length();if(pLen > sLen) return list;Map<Character, Integer> need = new HashMap<>();Map<Character, Integer> window = new HashMap<>();for(char c : p.toCharArray()) {need.put(c, need.getOrDefault(c, 0)+1);}int left = 0, right = 0, valid = 0;while(right < sLen) {char rc = s.charAt(right);right++;if(need.containsKey(rc)) {window.put(rc, window.getOrDefault(rc, 0)+1);if(window.get(rc).equals(need.get(rc))) {valid++;}}if(right - left == pLen) {if(valid == need.size()) {list.add(left);}char lc = s.charAt(left);left++;if(need.containsKey(lc)) {if(window.get(lc).equals(need.get(lc))) {valid--;}window.put(lc, window.get(lc)-1);}}}return list;}
}
五、560. 和为 K 的子数组
题目链接:https://leetcode.cn/problems/subarray-sum-equals-k/description/?envType=study-plan-v2&envId=top-100-liked
思路:求和为k的子数组,其实就是前缀和,和使用前缀和数组的题目有点像,但是为了少一层for,把原本要存入前缀和数组的值,都存进了hashmap,然后只需要用preSum - k 去map中寻找value即可。
class Solution {public int subarraySum(int[] nums, int k) {Map<Integer, Integer> map = new HashMap<>();map.put(0, 1);int count = 0, preSum = 0;for(int i = 0; i < nums.length; i++) {preSum += nums[i];if(map.containsKey(preSum - k)) {count += map.get(preSum - k);}map.put(preSum, map.getOrDefault(preSum, 0)+1);}return count;}
}
这篇关于力扣爆刷第84天之hot100五连刷6-10的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!