力扣深度优先搜索练习题(恢复二叉搜索树、相同的树)

123 阅读3分钟

恢复二叉搜索树

来源:力扣(LeetCode) 链接:leetcode.cn/problems/re…

给你二叉搜索树的根节点 root ,该树中的 恰好 两个节点的值被错误地交换。请在不改变其结构的情况下,恢复这棵树 。

示例 1:

图片.png

输入:root = [1,3,null,null,2]

输出:[3,1,null,null,2]

解释:3 不能是 1 的左孩子,因为 3 > 1 。交换 13 使二叉搜索树有效。

示例 2:

图片.png

输入:root = [3,1,4,null,null,2]

输出:[2,1,4,null,null,3]

解释:2 不能在 3 的右子树中,因为 2 < 3 。交换 23 使二叉搜索树有效。

提示:

  • 树上节点的数目在范围 [2, 1000] 内
  • -231 <= Node.val <= 231 - 1

代码

class Solution {
    private TreeNode first; // 第一个需要交换的节点
    private TreeNode second; // 第二个需要交换的节点
    private TreeNode prev; // 用于记录中序遍历中的前一个节点
    
    public void recoverTree(TreeNode root) {
        first = null;
        second = null;
        prev = null;
        
        // 中序遍历二叉树,查找需要交换的节点
        inorder(root);
        
        // 交换两个节点的值
        int temp = first.val;
        first.val = second.val;
        second.val = temp;
    }
    
    private void inorder(TreeNode node) {
        if (node == null) {
            return;
        }
        
        inorder(node.left);
        
        // 判断当前节点和前一个节点的大小关系
        if (prev != null && prev.val > node.val) {
            if (first == null) {
                first = prev;
            }
            second = node;
        }
        prev = node;
        
        inorder(node.right);
    }
}

思路分析

  1. 创建三个实例变量 firstsecondprev,分别用于记录第一个需要交换的节点、第二个需要交换的节点和中序遍历中的前一个节点。
  2. 调用辅助函数 inorder 进行中序遍历,传入根节点 root
  3. 在辅助函数中,首先判断当前节点是否为空,如果为空则返回。
  4. 递归调用 inorder 函数,先遍历左子树。
  5. 在中序遍历过程中,判断当前节点和前一个节点的大小关系,如果前一个节点的值大于当前节点的值,说明这两个节点被错误交换了。
  6. 如果 first 为空,将前一个节点赋值给 first;如果 first 不为空,将当前节点赋值给 second
  7. 更新前一个节点为当前节点。
  8. 最后,完成中序遍历后,交换 firstsecond 两个节点的值。
  9. 完成交换后,原本被错误交换的节点就得到了修复。

相同的树

来源:力扣(LeetCode) 链接:leetcode.cn/problems/sa…

给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。

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

示例 1:

输入:p = [1,2,3], q = [1,2,3]

输出:true

示例 2:

输入:p = [1,2], q = [1,null,2]

输出:false

示例 3:

输入:p = [1,2,1], q = [1,1,2]

输出:false

提示:

  • 两棵树上的节点数目都在范围 [0, 100] 内
  • -104 <= Node.val <= 104

代码

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);
    }
}

思路分析

  1. 首先判断两个节点 pq 是否都为空,如果是,则说明两棵树相同,返回 true
  2. 接着判断其中一个节点为空,另一个节点不为空的情况,这时候两棵树不相同,返回 false
  3. 再判断两个节点的值是否相等,如果不相等,则说明两棵树不相同,返回 false
  4. 最后,递归判断两个节点的左子树和右子树是否相同,即调用 isSameTree(p.left, q.left)isSameTree(p.right, q.right)
  5. 如果左子树和右子树都相同,返回 true;否则返回 false