• Day41LC+好未来


    1. 最多能完成排序的块 II

    这个问题和“最多能完成排序的块”相似,但给定数组中的元素可以重复,输入数组最大长度为2000,其中的元素最大为10**8。
    arr是一个可能包含重复元素的整数数组,我们将这个数组分割成几个“块”,并将这些块分别进行排序。之后再连接起来,使得连接的结果和按升序排序后的原数组相同。我们最多能将数组分成多少块?

    分析:

    排序块的充分条件是:此块中最大数字为 headhead , 若此块后面的所有数字都 >= head ,则此块为排序块。

    方法一:辅助栈

    可以遍历一遍数组arr,动态判断到目前数字 num 为止最多能分出多少排序块,并保存每个排序块的最大值 head 。每遍历到下个数字 num,动态判断前面所有的排序块是否成立,并更新所有排序块:

    • 当某排序块 num < head :将此排序块[A]与 num 合并,形成新排序块[A | num],最大值仍为 head;
    • 当某排序快num>=head:原排序块保留,并新加排序块 [num]。
      对于整个数组的排序块,其 head大小是从左到右递增的。因此,若给数组尾部加入一个随机正整数 n ,尾部的排序块更容易被合并(最先满足 num < head )。当 n 值较小时( < 前面多个排序块的 head ),则需按尾部到首部的顺序合并多个排序块。使用 栈 保存排序块最大值 head 。在遍历过程中,通过维护栈的 head 序列,实现排序块的动态更新。
    class Solution {
        public int maxChunksToSorted(int[] arr) {
            LinkedList<Integer> stack = new LinkedList<Integer>();
            for(int num : arr) {
                if(!stack.isEmpty() && num < stack.getLast()) {
                    int head = stack.removeLast();
                    while(!stack.isEmpty() && num < stack.getLast()) stack.removeLast();
                    stack.addLast(head);
                }
                else stack.addLast(num);
            }
            return stack.size();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    贪心+前缀最大值+后缀最小值
    1. 如果前缀 [… i) 的最大值 <= 后缀 [i …] 的最小值,则意味着 i 及其右侧的元素都能“守得住”,即:原数组排序后,[i] 无需跨到左侧,此时增加一个分块,对排序结果无影响;
    2. 否则,意味着 [i] 位置“守不住”,在原数组排序后,需要将其移到左侧,因此它不能单独成一个分块,此时分块不能增加;
    class Solution {
        public int maxChunksToSorted(int[] arr) {
            if (arr.length == 0) return 0;
            int[] rightMin = new int[arr.length];
            int leftMax = arr[0];
            rightMin[arr.length-1] = arr[arr.length-1];
            for (int i = arr.length-2; i >= 0 ; i--) {
                rightMin[i] = Math.min(arr[i], rightMin[i+1]);
            }
            int res = 1;
            for (int i = 1; i < arr.length; i++) {
                if (leftMax <= rightMin[i]) res++;
                leftMax = Math.max(leftMax, arr[i]);
            }
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    2. 岛屿数量

    给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。

    岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

    此外,你可以假设该网格的四条边均被水包围。

    分析:

    DFS。扫描整个二维网格。如果一个位置为 1,则以其为起始节点开始进行深度优先搜索。在深度优先搜索的过程中,每个搜索到的 1 都会被重新标记为 0。最终岛屿的数量就是我们进行深度优先搜索的次数。

    class Solution {
        public int numIslands(char[][] grid) {
            if (grid.length == 0 || grid[0].length == 0) return 0;
            int lines = grid.length;
            int rows = grid[0].length;
            int ans = 0;
            for (int i = 0; i < lines; i++) {
                for (int j = 0; j < rows; j++) {
                    if (grid[i][j] == '1')
                    {
                        traceback(grid, i, j);
                        ans++;
                    }
                }
            }
            return ans;
        }
    
        private void traceback(char[][] grid, int i, int j) {
            if (i<0 || i>=grid.length || j<0 || j>=grid[0].length || grid[i][j] == '0') return;
            grid[i][j] = '0';
            traceback(grid, i-1, j);
            traceback(grid, i+1, j);
            traceback(grid, i, j-1);
            traceback(grid, i, j+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

    3. 二叉树的前序遍历

    给你二叉树的根节点 root ,返回它节点值的 前序 遍历。

    分析:

    DFS。

    class Solution {
        public List<Integer> preorderTraversal(TreeNode root) {
            List<Integer> res = new ArrayList<>();
            PreOrder(root, res);
            return res;
        }
    
        private void PreOrder(TreeNode root, List<Integer> res) {
            if (root == null) return;
            res.add(root.val);
            PreOrder(root.left, res);
            PreOrder(root.right, res);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    前端HTML5 +CSS3 5.CSS布局 1 CSS三大特性 && 2 PxCook的基本使用 && 3 盒子模型
    【多条件筛选】js简单实现多条件过滤数组对象,返回新的数组
    汇编B800显示字符和颜色
    MyBatis框架一二级缓存含代码演示
    基于Python实现的AStar求解八数码问题
    跨平台开发方案调研
    大厂Java面试必备面试题:基础语法-数据类型-编码-注释-运算符-关键字-流程控制语句
    vue-vuex详解
    使用AlphaFold2进行蛋白质结构预测
    L1926. bfs
  • 原文地址:https://blog.csdn.net/weixin_49546933/article/details/126326250