面试经典算法系列之二叉树2 --对称二叉树

面试经典算法17 - 对称二叉树

LeetCode.101
公众号:阿Q技术站

问题描述

给你一个二叉树的根节点 root , 检查它是否轴对称。

示例 1:

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

示例 2:

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

提示:

  • 树中节点数目在范围 [1, 1000]
  • -100 <= Node.val <= 100

思路

递归
  1. 如果树为空,则是轴对称的,直接返回 true。
  2. 编写一个辅助函数 isSymmetricHelper,该函数接受两个节点作为参数,分别表示当前层级的左右节点。
  3. isSymmetricHelper中,进行以下判断:
    • 如果两个节点都为空,则返回 true。
    • 如果只有一个节点为空,或者两个节点的值不相等,则返回 false。
    • 否则,递归地判断左节点的左子树和右节点的右子树是否对称,并且左节点的右子树和右节点的左子树是否对称。
  4. 最终返回 isSymmetricHelper(root->left, root->right),表示从根节点开始的二叉树是否轴对称。
非递归
  1. 首先检查根节点是否为空,若为空则返回 true。
  2. 创建一个队列 q,并将根节点的左右子节点依次入队。
  3. 每次从队列中取出两个节点,分别表示当前层级对称的左右节点。
  4. 如果两个节点都为空,则继续下一次循环。
  5. 如果其中一个节点为空,或者两个节点的值不相等,则返回 false。
  6. 将左节点的左子节点与右节点的右子节点、左节点的右子节点与右节点的左子节点依次入队。
  7. 循环直到队列为空,返回 true。

图解

  1. 创建一个队列 q,并将根节点的左右子节点依次入队。

  1. 当队列不为空时,将左右节点分别弹出队列。

  1. 将左节点的左子节点与右节点的右子节点、左节点的右子节点与右节点的左子节点依次入队。

  1. 队列不为空,将节点依次弹出队列。

此时,队列为空,返回 true。

参考代码

C++
递归
#include <iostream>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

// 辅助函数,判断以left和right为根节点的两棵树是否轴对称
bool isSymmetricHelper(TreeNode* left, TreeNode* right) {
    // 如果两个节点都为空,则对称
    if (!left && !right) {
        return true;
    }
    // 如果只有一个节点为空,或者两个节点的值不相等,则不对称
    if (!left || !right || left->val != right->val) {
        return false;
    }
    // 递归判断左节点的左子树和右节点的右子树,以及左节点的右子树和右节点的左子树是否对称
    return isSymmetricHelper(left->left, right->right) && isSymmetricHelper(left->right, right->left);
}

// 主函数,检查二叉树是否轴对称
bool isSymmetric(TreeNode* root) {
    if (!root) {
        return true; // 空树是对称的
    }
    return isSymmetricHelper(root->left, root->right);
}

// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
    if (index >= nodes.size() || nodes[index] == -1) {
        return nullptr; // 如果节点为空,则返回nullptr
    }
    TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
    root->left = createTree(nodes, 2 * index + 1); // 创建左子树
    root->right = createTree(nodes, 2 * index + 2); // 创建右子树
    return root; // 返回当前节点
}

int main() {
    // 输入二叉树的先序遍历序列,-1表示空节点
    vector<int> nodes = {1, 2, 2, 3, 4, 4, 3};
    TreeNode* root = createTree(nodes, 0); // 创建二叉树
    cout << (isSymmetric(root) ? "true" : "false") << endl; // 检查是否轴对称

    return 0;
}
非递归
#include <iostream>
#include <queue>

using namespace std;

// 二叉树节点的定义
struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if (!root) {
            return true; // 空树是对称的
        }

        queue<TreeNode*> q; // 辅助队列,用于层级遍历
        q.push(root->left); // 将根节点的左子节点入队
        q.push(root->right); // 将根节点的右子节点入队

        while (!q.empty()) {
            TreeNode* leftNode = q.front(); // 当前层级对称的左节点
            q.pop();
            TreeNode* rightNode = q.front(); // 当前层级对称的右节点
            q.pop();

            if (!leftNode && !rightNode) {
                continue; // 左右节点都为空,继续下一次循环
            }
            if (!leftNode || !rightNode || leftNode->val != rightNode->val) {
                return false; // 左右节点有一个为空,或者值不相等,返回 false
            }

            // 将左节点的左子节点与右节点的右子节点、左节点的右子节点与右节点的左子节点依次入队
            q.push(leftNode->left);
            q.push(rightNode->right);
            q.push(leftNode->right);
            q.push(rightNode->left);
        }

        return true; // 遍历完所有对称节点,返回 true
    }
};

// 创建二叉树
TreeNode* createTree(vector<int>& nodes, int index) {
    if (index >= nodes.size() || nodes[index] == -1) {
        return nullptr; // 如果节点为空,则返回nullptr
    }
    TreeNode* root = new TreeNode(nodes[index]); // 创建当前节点
    root->left = createTree(nodes, 2 * index + 1); // 创建左子树
    root->right = createTree(nodes, 2 * index + 2); // 创建右子树
    return root; // 返回当前节点
}

int main() {
    vector<int> nodes = {1, 2, 2, 3, 4, 4, 3}; // 对称的二叉树的层序遍历序列
    TreeNode* root = createTree(nodes, 0); // 创建二叉树
    Solution solution;
    bool result = solution.isSymmetric(root); // 判断二叉树是否对称
    cout << (result ? "true" : "false") << endl; // 输出结果

    return 0;
}
Java
import java.util.LinkedList;
import java.util.Queue;

// 二叉树节点的定义
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) {
        val = x;
    }
}

class Solution {
    public boolean isSymmetric(TreeNode root) {
        if (root == null) {
            return true; // 空树是对称的
        }

        Queue<TreeNode> q = new LinkedList<>(); // 辅助队列,用于层级遍历
        q.offer(root.left); // 将根节点的左子节点入队
        q.offer(root.right); // 将根节点的右子节点入队

        while (!q.isEmpty()) {
            TreeNode leftNode = q.poll(); // 当前层级对称的左节点
            TreeNode rightNode = q.poll(); // 当前层级对称的右节点

            if (leftNode == null && rightNode == null) {
                continue; // 左右节点都为空,继续下一次循环
            }
            if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
                return false; // 左右节点有一个为空,或者值不相等,返回 false
            }

            // 将左节点的左子节点与右节点的右子节点、左节点的右子节点与右节点的左子节点依次入队
            q.offer(leftNode.left);
            q.offer(rightNode.right);
            q.offer(leftNode.right);
            q.offer(rightNode.left);
        }

        return true; // 遍历完所有对称节点,返回 true
    }
}

public class Main {
    public static void main(String[] args) {
        int[] nodes = {1, 2, 2, 3, 4, 4, 3}; // 对称的二叉树的层序遍历序列
        TreeNode root = createTree(nodes, 0); // 创建二叉树
        Solution solution = new Solution();
        boolean result = solution.isSymmetric(root); // 判断二叉树是否对称
        System.out.println(result ? "true" : "false"); // 输出结果
    }

    // 创建二叉树
    public static TreeNode createTree(int[] nodes, int index) {
        if (index >= nodes.length || nodes[index] == -1) {
            return null; // 如果节点为空,则返回null
        }
        TreeNode root = new TreeNode(nodes[index]); // 创建当前节点
        root.left = createTree(nodes, 2 * index + 1); // 创建左子树
        root.right = createTree(nodes, 2 * index + 2); // 创建右子树
        return root; // 返回当前节点
    }
}
Python
from collections import deque

# 二叉树节点的定义
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

class Solution:
    def isSymmetric(self, root: TreeNode) -> bool:
        if not root:
            return True  # 空树是对称的

        q = deque()  # 辅助队列,用于层级遍历
        q.append(root.left)  # 将根节点的左子节点入队
        q.append(root.right)  # 将根节点的右子节点入队

        while q:
            left_node = q.popleft()  # 当前层级对称的左节点
            right_node = q.popleft()  # 当前层级对称的右节点

            if not left_node and not right_node:
                continue  # 左右节点都为空,继续下一次循环
            if not left_node or not right_node or left_node.val != right_node.val:
                return False  # 左右节点有一个为空,或者值不相等,返回 false

            # 将左节点的左子节点与右节点的右子节点、左节点的右子节点与右节点的左子节点依次入队
            q.append(left_node.left)
            q.append(right_node.right)
            q.append(left_node.right)
            q.append(right_node.left)

        return True  # 遍历完所有对称节点,返回 true

# 创建二叉树
def create_tree(nodes, index):
    if index >= len(nodes) or nodes[index] is None:
        return None  # 如果节点为空,则返回 None
    root = TreeNode(nodes[index])  # 创建当前节点
    root.left = create_tree(nodes, 2 * index + 1)  # 创建左子树
    root.right = create_tree(nodes, 2 * index + 2)  # 创建右子树
    return root  # 返回当前节点

# 测试代码
nodes = [1, 2, 2, 3, 4, 4, 3]  # 对称的二叉树的层序遍历序列
root = create_tree(nodes, 0)  # 创建二叉树
solution = Solution()
result = solution.isSymmetric(root)  # 判断二叉树是否对称
print("true" if result else "false")  # 输出结果
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值