赞
踩
题目链接:https://leetcode.cn/problems/sliding-window-maximum/description/?envType=study-plan-v2&envId=top-100-liked
思路:求滑动窗口内的最大值,自然要维护一个滑动窗口,这里我们使用一个队列来表示滑动窗口,既然要记录最大值,那么我们在添加元素时,自然要如果队尾元素小于当前元素,队尾元素就应该出队,直到没有小于当前元素的存在,然后把当前元素入队,这样队头位置就是滑动窗口内的最大值。
class Solution { public int[] maxSlidingWindow(int[] nums, int k) { int[] res = new int[nums.length - k + 1]; Queue queue = new Queue(); for (int i = 0; i < k; i++) { queue.push(nums[i]); } int j = 0; res[j++] = queue.getMax(); for (int i = k; i < nums.length; i++) { queue.pop(nums[i-k]); queue.push(nums[i]); res[j++] = queue.getMax(); } return res; } class Queue { LinkedList<Integer> stack = new LinkedList<>(); void push(int n) { while (!stack.isEmpty() && n > stack.getLast()) { stack.pollLast(); } stack.addLast(n); } void pop(int n) { if (n == stack.getFirst()) { stack.pollFirst(); } } int getMax() { return stack.getFirst(); } } }
题目链接:https://leetcode.cn/problems/minimum-window-substring/?envType=study-plan-v2&envId=top-100-liked
思路:最小覆盖子串问题,很显然是滑动窗口,如下代码就是滑动窗口的模板。首先是一直扩大窗口,当窗口满足条件后,就开始缩小窗口,直到窗口不再满足条件,即又开始扩大窗口。
class Solution { public String minWindow(String s, String t) { Map<Character, Integer> need = new HashMap<>(); Map<Character, Integer> window = new HashMap<>(); for(char c : t.toCharArray()) { need.put(c, need.getOrDefault(c, 0) + 1); } int left = 0, right = 0, min = Integer.MAX_VALUE, vaild = 0; int[] xy = new int[2]; while(right < s.length()) { 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))) { vaild++; } } while(vaild == need.size()) { int len = right-left; if(len < min) { min = len; xy[0] = left; xy[1] = right; } char lc = s.charAt(left); left++; if(need.containsKey(lc)) { if(window.get(lc).equals(need.get(lc))) { vaild--; } window.put(lc, window.get(lc)-1); } } } return min == Integer.MAX_VALUE ? "" : s.substring(xy[0], xy[1]); } }
题目链接:https://leetcode.cn/problems/maximum-subarray/description/?envType=study-plan-v2&envId=top-100-liked
思路:本题可以使用贪心算法和动态规划,贪心如下,如果子数组和大于零,就一直加并记录最大值,这个过程中是肯能达到最大值的,只要子数组和小于零,就可以另起一个新子数组了。
贪心算法:
class Solution {
public int maxSubArray(int[] nums) {
int max = Integer.MIN_VALUE, sum = 0;
for(int i = 0; i < nums.length; i++) {
sum += nums[i];
max = Math.max(max, sum);
if(sum < 0) {
sum = 0;
}
}
return max;
}
}
动态规划:定义dp[i]表示区间[0, i]中以nums[i]为结尾的最大子数组和,动态规划就是选择,可以选择是否以讲当前元素加入左边的子数组,不加入就单开一个子数组。dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
class Solution {
public int maxSubArray(int[] nums) {
int[] dp = new int[nums.length];
dp[0] = nums[0];
int max = nums[0];
for(int i = 1; i < nums.length; i++) {
dp[i] = Math.max(dp[i-1]+nums[i], nums[i]);
max = Math.max(max, dp[i]);
}
return max;
}
}
题目链接:https://leetcode.cn/problems/merge-intervals/description/?envType=study-plan-v2&envId=top-100-liked
思路:合并区间也是一个经典题目,只需要把左边界排序,只要有重叠的,就合并,无重叠就保存之前的区间,然后新开一个区间。
class Solution { public int[][] merge(int[][] intervals) { Arrays.sort(intervals, (a, b) -> a[0]-b[0]); List<int[]> list = new ArrayList<>(); int left = intervals[0][0], right = intervals[0][1]; for(int i = 1; i < intervals.length; i++) { if(intervals[i][0] <= right) { right = Math.max(right, intervals[i][1]); }else { list.add(new int[]{left, right}); left = intervals[i][0]; right = intervals[i][1]; } } list.add(new int[]{left, right}); int[][] res = new int[list.size()][2]; for(int i = 0; i < list.size(); i++) { res[i] = list.get(i); } return res; } }
题目链接:https://leetcode.cn/problems/rotate-array/description/?envType=study-plan-v2&envId=top-100-liked
思路:nums = [1,2,3,4,5,6,7], k = 3,要求向右移动数组,且是循环的,很经典的题目,直接全部翻转,然后再分段翻转。
class Solution { public void rotate(int[] nums, int k) { k = k % nums.length; reverse(nums, 0, nums.length-1); reverse(nums, 0, k-1); reverse(nums, k, nums.length-1); } void reverse(int[] nums, int i, int j) { while(i < j) { int temp = nums[i]; nums[i] = nums[j]; nums[j] = temp; i++; j--; } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。