LEETCODE DFS基础篇(已完成)

本文深入探讨了二叉树的多种算法,包括相同树、平衡二叉树、对称二叉树等概念的判断方法,以及二叉树的最大深度、最小深度、路径总和等问题的解决策略,通过实例讲解,帮助读者掌握二叉树的关键操作。

1

  1. 相同的树
    给定两个二叉树,编写一个函数来检验它们是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例 1:

输入: 1 1
/ \ /
2 3 2 3

    [1,2,3],   [1,2,3]

输出: true
示例 2:

输入: 1 1
/
2 2

    [1,2],     [1,null,2]

输出: false
示例 3:

输入: 1 1
/ \ /
2 1 1 2

    [1,2,1],   [1,1,2]

输出: false

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        if(p==null&&q==null)
        return true;
        if(p==null||q==null)
        return false;
        if(p.val!=q.val)
        return false;
        return isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
    }
}

2

  1. 平衡二叉树
    给定一个二叉树,判断它是否是高度平衡的二叉树。

本题中,一棵高度平衡二叉树定义为:

一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

示例 1:

给定二叉树 [3,9,20,null,null,15,7]

3

/
9 20
/
15 7
返回 true 。

示例 2:

给定二叉树 [1,2,2,3,3,null,null,4,4]

   1
  / \
 2   2
/ \

3 3
/
4 4
返回 false 。

思路:先判断当前节点的左右子树是否满足平衡,具体是取得左右子树的最大深度,若绝对值大于1,则不平衡,返回false;否则认为平衡,继续判断左右子树是否平衡;

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null)
        return true;
        int left=getDepth(root.left,0);
        int right=getDepth(root.right,0);
        if(Math.abs(left-right)>1){
            return false;
        }
        return isBalanced(root.left)&&isBalanced(root.right);
    }

    public int getDepth(TreeNode root,int depth){
        if(root==null)
        return depth;
        int left=getDepth(root.left,depth+1);
        int right=getDepth(root.right,depth+1);
        return Math.max(left,right);
    }
}

3

  1. 对称二叉树
    给定一个二叉树,检查它是否是镜像对称的。

例如,二叉树 [1,2,2,3,4,4,3] 是对称的。

1

/
2 2
/ \ /
3 4 4 3

但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:

1

/
2 2
\
3 3

思路:判断一颗树是否为镜像树的规则是:如果一个树的左子树与右子树镜像对称,那么这个树是对称的。因此,该问题可以转化为:两个树在什么情况下互为镜像?

如果同时满足下面的条件,两个树互为镜像:

它们的两个根结点具有相同的值。
每个树的右子树都与另一个树的左子树镜像对称。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
       return isMirror(root,root);
    }

    public boolean isMirror(TreeNode t1,TreeNode t2){
        if(t1==null&&t2==null)
        return true;
        if(t1==null||t2==null)
        return false;
        return (t1.val==t2.val)&&(isMirror(t1.left,t2.right))&&isMirror(t1.right,t2.left);
    }
}

4

  1. 二叉树的最大深度
    给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点。

示例:
给定二叉树 [3,9,20,null,null,15,7],

3

/
9 20
/
15 7
返回它的最大深度 3 。

思路:利用一个变量记录最大深度,每当一个节点为null时,比较到该节点的深度与max记录的最大深度,循环即可

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int max = 0;

    public int maxDepth(TreeNode root) {
        if(root==null)
        return max;
        getMax(root,0);
        return max;
    }

    public void getMax(TreeNode root,int depth){
        if(root==null){
            max=Math.max(max,depth);
            return;
        }
        getMax(root.left,depth+1);
        getMax(root.right,depth+1);
    }
}

5

  1. 二叉树的最小深度
    给定一个二叉树,找出其最小深度。

最小深度是从根节点到最近叶子节点的最短路径上的节点数量。

说明: 叶子节点是指没有子节点的节点。

示例:

给定二叉树 [3,9,20,null,null,15,7],

3

/
9 20
/
15 7

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    int min=Integer.MAX_VALUE;
    public int minDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        getMin(root,1);
        return min;
    }

    public void getMin(TreeNode root,int depth){
        if(root.left==null&&root.right==null){
            if(depth<min)
            min=depth;
            return;
        }
        if(root.left!=null)
        getMin(root.left,depth+1);
        if(root.right!=null)
        getMin(root.right,depth+1);
    }
}

6

  1. 路径总和
    给定一个二叉树和一个目标和,判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和。

说明: 叶子节点是指没有子节点的节点。

示例:
给定如下二叉树,以及目标和 sum = 22,

          5
         / \
        4   8
       /   / \
      11  13  4
     /  \      \
    7    2      1

返回 true, 因为存在目标和为 22 的根节点到叶子节点的路径 5->4->11->2。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean hasPathSum(TreeNode root, int sum) {
        if(root==null){
            return false;
        }
        return has(root,sum);
    }

    public boolean has(TreeNode root,int sum){
        if(root.left==null&&root.right==null){
            if(root.val==sum){
                return true;
            }
            return false;
        }
        if(root.left!=null&&root.right!=null){
            return has(root.left,sum-root.val)||has(root.right,sum-root.val);
        }else{
            return root.left==null?has(root.right,sum-root.val):has(root.left,sum-root.val);
        }
       
    }
}

7

  1. 二叉树的所有路径
    给定一个二叉树,返回所有从根节点到叶子节点的路径。

说明: 叶子节点是指没有子节点的节点。

示例:

输入:

1
/
2 3

5

输出: [“1->2->5”, “1->3”]

解释: 所有根节点到叶子节点的路径为: 1->2->5, 1->3

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<String> ans = new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
        if(root==null)
        return ans;
        String tmp = ""+root.val;
        if(root.left==null&&root.right==null){
            ans.add(tmp);
            return ans;
        }
        if(root.left!=null)
        dfs(root.left,tmp);
        if(root.right!=null){
            dfs(root.right,tmp);
        }
        return ans;
    }

    public void dfs(TreeNode root,String tmp){
        tmp+="->"+root.val;
        if(root.left==null&&root.right==null){
            ans.add(new String(tmp));
            return;
        }
        if(root.left!=null){
            dfs(root.left,tmp);
        }
        if(root.right!=null){
            dfs(root.right,tmp);
        }
    }
}

8

  1. 图像渲染
    有一幅以二维整数数组表示的图画,每一个整数表示该图画的像素值大小,数值在 0 到 65535 之间。

给你一个坐标 (sr, sc) 表示图像渲染开始的像素值(行 ,列)和一个新的颜色值 newColor,让你重新上色这幅图像。

为了完成上色工作,从初始坐标开始,记录初始坐标的上下左右四个方向上像素值与初始坐标相同的相连像素点,接着再记录这四个方向上符合条件的像素点与他们对应四个方向上像素值与初始坐标相同的相连像素点,……,重复该过程。将所有有记录的像素点的颜色值改为新的颜色值。

最后返回经过上色渲染后的图像。

示例 1:

输入:
image = [[1,1,1],[1,1,0],[1,0,1]]
sr = 1, sc = 1, newColor = 2
输出: [[2,2,2],[2,2,0],[2,0,1]]
解析:
在图像的正中间,(坐标(sr,sc)=(1,1)),
在路径上所有符合条件的像素点的颜色都被更改成2。
注意,右下角的像素没有更改为2,
因为它不是在上下左右四个方向上与初始点相连的像素点。

class Solution {

    int[] dx={-1,0,1,0};
    int[] dy={0,1,0,-1};
    public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
        if(image==null)
        return image;
        int row=image.length;
        int col=image[0].length;
        if(sr>=row||sc>=col)
        return image;
        int color=image[sr][sc];
        if(color==newColor)
        return image;
        //image[sr][sc]=newColor;
        dfs(image,sr,sc,newColor,color);
        return image;
    }

    public void dfs(int[][] image,int x,int y,int newColor,int color){
        if(image[x][y]!=color){
            return;
        }
        image[x][y]=newColor;
        for(int i=0;i<4;i++){
            int a=x+dx[i];
            int b=y+dy[i];
            if(a>=0&&a<image.length&&b>=0&&b<image[0].length&&image[a][b]==color){

                dfs(image,a,b,newColor,color);
            }
        }
    }
}

9

  1. 叶子相似的树
    请考虑一颗二叉树上所有的叶子,这些叶子的值按从左到右的顺序排列形成一个 叶值序列 。

举个例子,如上图所示,给定一颗叶值序列为 (6, 7, 4, 9, 8) 的树。

如果有两颗二叉树的叶值序列是相同,那么我们就认为它们是 叶相似 的。

如果给定的两个头结点分别为 root1 和 root2 的树是叶相似的,则返回 true;否则返回 false 。

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public boolean leafSimilar(TreeNode root1, TreeNode root2) {
        List<Integer> list1=new ArrayList<>();
        List<Integer> list2=new ArrayList<>();
        dfs(root1,list1);
        dfs(root2,list2);
        if(list1.size()==list2.size()){
            for(int i=0;i<list1.size();i++){
                if(list1.get(i)!=list2.get(i))
                return false;
            }
            return true;
        }else
        return false;
    }

    public void dfs(TreeNode root,List<Integer> list){
        if(root==null)
        return;
        if(root.left==null&&root.right==null){
            list.add(root.val);
            return;
        }
        dfs(root.left,list);
        dfs(root.right,list);
    }
}

10

  1. 递增顺序查找树
    给你一个树,请你 按中序遍历 重新排列树,使树中最左边的结点现在是树的根,并且每个结点没有左子结点,只有一个右子结点。

示例 :

输入:[5,3,6,2,4,null,8,1,null,null,null,7,9]

   5
  / \
3    6

/ \
2 4 8
/ / \
1 7 9

输出:[1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null,9]

1

2

3

4

5

6

7

8

9

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    List<Integer> list = new ArrayList<>();
    public TreeNode increasingBST(TreeNode root) {
        if(root==null)
        return root;
        dfs(root,list);
        TreeNode ans = new TreeNode(list.get(0));
        TreeNode cur = ans;
        int index=1;
        while(index<list.size()){
            TreeNode tmp=new TreeNode(list.get(index));
            cur.right=tmp;
            cur=tmp;
            index++;
        }
        return ans;
    }
    public void dfs(TreeNode root,List<Integer> list){
        if(root==null){
            return;
        }
     
            dfs(root.left,list);

        list.add(root.val);
        dfs(root.right,list);
    }
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值