LeetCode54螺旋矩阵+538. 把二叉搜索树转换为累加树+73. 矩阵置零

0 阅读4分钟

 这三道题分别来自Hot100与代码随想录,文章仅记录作者刷算法题过程中的所思所感,希望对你有帮助,如有错误欢迎指正,我是栗子君,欢迎大家一起监督、学习。

一、螺旋矩阵

题目描述

​编辑

思路

  按照螺旋顺序,定义好上下左右四个边界 按照左->右 上->下 右->左 下->上的顺序遍历数组,同时每每遇到边界即碰墙时就更新边界,同时要在每次更新边界后判断边界是否满足条件,即上边界在上下边界在下,左右边界同理。如果不满足则跳出,避免重复遍历某个元素

复杂度

  • 时间复杂度: O(mn)
  • 空间复杂度: O(mn)

Code

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> res = new ArrayList<>();
        if(matrix==null) return res;
        
        //定义左右边界
        int above = 0;
        int below = matrix.length-1;
        int left = 0;
        int right = matrix[0].length-1;
        

        while(left<=right && above<=below){
            //左->右
            for(int i=left; i<=right; i++){
                res.add(matrix[above][i]);
            }
            //更新上边界
            above++;

            if(above>below) break;

            //上->下
            for(int i=above; i<=below; i++){
                res.add(matrix[i][right]);
            }
            //更新右边界
            right--;

            if(right<left) break;

            //右->左
            for(int i=right; i>=left; i--){
                res.add(matrix[below][i]);
            }
            //更新下边界
            below--;

            if(above>below) break;

            //下->上
            for(int i=below; i>=above; i--){
                res.add(matrix[i][left]);
            }
            //更新左边界
            left++;
            if(right<left) break;
        }

        return res;
    }
}

二、把二叉搜索树转换为累加树

题目描述

​编辑

​编辑

思路

  对于二叉搜索树,我们知道如果采用我们常说的中序遍历,也就是左根右的顺序去遍历这棵树,会得到一个递增序列。那么如果我们把顺序倒过来,按照右根左的顺序遍历二叉搜索树,就可以得到一个递减序列。为什么要这样做呢,因为我们要累加比当前节点值大的所有元素,那么从最大的元素开始访问就可以逐步求得下一个元素需要的累加值,有点类似于前缀。如果我们先访问小的元素,我们无法得知比当前元素大的元素的累加和是多少。

​编辑

复杂度

  • 时间复杂度: O(mn)
  • 空间复杂度: O(mn)

Code

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    int sum = 0;
    public TreeNode convertBST(TreeNode root) {
        dfs(root);
        return root;
    }

    public void dfs(TreeNode root){
        if(root==null) return ;

        dfs(root.right);

        root.val +=sum;
        sum = root.val;

        dfs(root.left);
    }
}

三、矩阵置零

题目描述

​编辑

思路

  我们可以利用第一行第一列存储置零信息 第一行的某个位置存储该列是否需要置为0 第一列的某个位置存储该行是否需要置为0。

  同时,第一行第一列本身可能含有零,我们还需额外记录第一行/列本身是否需要置为0。 注意为什么用第一行第一列存储置零信息不考虑原本元素被覆盖呢?这是因为当我们遍历到每个元素为0时,这个元素所在行所在列就要置为0,那么第一行/第一列存储置0信息的位置也一定会被置为0,因此不必担心元素会被覆盖,只要第一行/列所在行/列存在0,他也一定会被置为0。但第一行/列本身是否存在0这个属性被改变了,所以要额外存储这部分信息。 如果对空间复杂度要求降低,也可以采用Set集合来存储需要置0的行列信息。

​编辑

复杂度

  • 时间复杂度: O(mn)
  • 空间复杂度: O(1)

Code

class Solution {
    public void setZeroes(int[][] matrix) {
        boolean row0 =false;
        boolean col0 = false;
        int m = matrix.length;
        int n = matrix[0].length;
        //第一行中是否含有零
        for(int i=0; i<n; i++){
            if(matrix[0][i]==0){
                row0 = true;
            }
        }

        //第一列中是否含零
        for(int i=0; i<m; i++){
            if(matrix[i][0]==0){
                col0 = true;
            }
        }

        //除第一行第一列之外的部分中需要置为0的行和列信息存储在第一行/列
        for(int i=1; i<m; i++){
            for(int j=1; j<n; j++){
                if(matrix[i][j]==0){
                    matrix[0][j] = 0;
                    matrix[i][0] = 0;
                }
            }
        }

        for(int i=1; i<m; i++){
            for(int j=1; j<n; j++){
                //当前元素所在行或所在列需要置零则将该元素置为0
                if(matrix[0][j]==0 || matrix[i][0]==0){
                    matrix[i][j] = 0;
                }
            }
        }

        //将第一行/第一列置为0
        if(row0){
            for(int i=0; i<n; i++){
                matrix[0][i] = 0;
            }
        }

        if(col0){
            for(int i=0; i<m; i++){
                matrix[i][0] = 0;
            }
        }


    }
}