剑指offer系列-面试题28-对称的二叉树(python)

文章目录

  • 1. 题目
  • 2. 解题思路
    • 2.1 思路1
    • 2.1 思路2
  • 3. 代码实现
    • 3.1 思路1
  • 4. 总结
  • 5. 参考文献

1. 题目

请实现一个函数,用来判断一棵二叉树是不是对称的。如果一棵二叉树和它的镜像一样,那么它是堆成的。例如,在如图4.3所示的3棵二叉树中,第一棵二叉树是对成的,二另外两棵不是。


5
6
7
8
6.
7.
5.

5
6
7
8
9
7.
5.

7
7.
.7
7..
7...
..7

2. 解题思路

2.1 思路1

要判断二叉树是否对称,那也就是:

  1. 判断根节点左子节点是否等于右子节点,
  2. 若相等,则判断左子节点的结构是否与右子节点的结构是一致的
  3. 然后递归或循环。

2.1 思路2

1.利用面试题27获得此二叉树的镜像
2.遍历二叉树,判断二叉树和镜像是否一样
但是觉得这样的效率有点低了。

3. 代码实现

3.1 思路1

递归版

def is_symmetrical(root):
	
	if root == None:
		return True
	return is_symmetrical_child(root.left, root.right)
	
def is_symmetrical_child(root1, root2):
	"""
	判断这两个树的结构是否一致
	"""
	# 两个节点是否都不存在
	if not root1 and not root2: # 基线条件
		return True
	# 仅有一个节点存在,直接返回False
	if root1 or root2: # 不会出现root1和root2同时为None的情况,因为这种情况,在上一个if就直接返回了,走不到这步
		return False
	# 两个节点的值不相等,直接返回False
	if root1.value != root2.value:
		return False
	# 递归
	return is_symmetrical_child(root1.left, root2.left) and is_symmetrical_child(root1.right, root2.right)
			

循环版
在循环时,一定要注意两棵树的遍历顺序是不一致的,而且也是镜像的

A: 根左右;B: 根右左
A: 左根右;B: 右根左
A: 左右根;B: 右左根

def is_symmetrical(root):
	
	if root == None:
		return True
	return is_symmetrical_child(root.left, root.right)
	
result = True
    queue1 = [] # 队列1
    queue2 = [] # 队列2
    queue1.append(root1)
    queue2.append(root2)
    
    # 循环结束的条件,至少有一个队列为空,或这两个队列长度不一致
    while queue1 and queue2 and len(queue1) == len(queue2):
        node1 = queue1.pop(0)
        node2 = queue2.pop(0)
        # 两个节点是否都不存在
        if not node1 and not node2: # 基线条件
            result = True
        # 这两个节点都存在
        elif node1 and node2: 
            # 两个节点的值不相等,直接返回False
            if node1.value != node2.value:
                return False
            else:
                result = True # 走到这一步表示这两个节点的值是相等的
                if node1.left and node2.right:
                    queue1.append(node1.left)
                    queue2.append(node2.right)
                if node1.right and node2.left:
                    queue1.append(node1.right)
                    queue2.append(node2.left)
                
        # 仅有一个节点存在,直接返回False
        # 不会出现root1和root2同时为None的情况,因为这种情况,在上一个if就直接返回了,走不到这步
        else: 
            return False
    print(len(queue1), len(queue2))
    if queue1 or queue2: # 判断退出循环后,这两个队列是否都为空,因为有可能一个子树是另一个子树的子结构
        result = False
    
    return result

class Node(object):
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right


if __name__ == '__main__':
    node1 = Node(1)
    node2 = Node(2)
    node2_ = Node(2)
    node4 = Node(4)
    node5 = Node(5)
    node4_ = Node(4)
    node5_ = Node(5)
    node8 = Node(8)
    node9 = Node(9)
    node8_ = Node(8)
    node9_ = Node(9)

    # 第一棵树
    node1.left = node2
    node1.right = node2_

    node2.left = node4
    node2.right = node5
    node2_.left = node5_
    node2_.right = node4_

    node4.left = node8
    node4.right = node9
    node4_.left = node9_
    node4_.right = node8_
    
    res = is_symmetrical(node1)
    print(res)
						

4. 总结

树的算法离不开递归和循环。树的遍历方法有三种:前序遍历、中序遍历和后序遍历,不同情况下可以选择合适的遍历方式,有利于解题。而在使用循环的时候一般都是使用队列来实现。

5. 参考文献

[1] 剑指offer丛书

你可能感兴趣的:(算法)