• 力扣爆刷第85天之hot100五连刷11-15


    力扣爆刷第85天之hot100五连刷11-15

    一、239. 滑动窗口最大值

    题目链接: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();
            }
        }
    }
    
    • 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

    二、76. 最小覆盖子串

    题目链接: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]);
        }
    }
    
    • 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

    三、53. 最大子数组和

    题目链接: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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    动态规划:定义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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    四、56. 合并区间

    题目链接: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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    五、189. 轮转数组

    题目链接: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--;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    MapStruct代码生成器使用
    764、最大加号标志
    【编程题】【Scratch二级】2022.09 小老鼠偷面包
    [论文阅读] 颜色迁移-N维pdf迁移
    【vue3】keep-alive缓存组件
    Arduino驱动TCS3200传感器(颜色传感器篇)
    ThinkPHP8学习笔记
    面试题 16.20. T9键盘-力扣双百代码
    1、Nio三大组件(channel-buffer)
    第十天机器视觉基础
  • 原文地址:https://blog.csdn.net/qq_43511039/article/details/136438033