(十二)|10.层序遍历 226.翻转二叉树 101.对称二叉树

10.层序遍历

层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。也就是图论中的广度优先遍历应用在二叉树上。

需要借用一个辅助数据结构即队列来实现,队列先进先出,符合一层一层遍历的逻辑,而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。


class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution(object):
    def levelOrder(self, root):
        queue=collections.deque([root])  #创建一个双端队列,并把根节点传入
        result=[]
        if not root:  # 根节点是一个列表,如果根节点为空,直接返回
            return []
        while queue:
            level=[]  # 存放每一层的节点
            size=len(queue)
            for _ in range(size):
                cur=queue.popleft()  # 获取队列队头元素并将其弹出
                level.append(cur.val)  # 把队头的值存到level列表中
                if cur.left:  # 如果当前节点有左孩子,就把左孩子加入队列中
                    queue.append(cur.left)
                if cur.right:  # 如果当前节点有右孩子,就把右孩子加入队列中
                    queue.append(cur.right)
            result.append(level)  #把这一层的节点存到result中
        return result

        

递归法(还需要理解):

递归的基本思路是,从根节点开始,递归地访问每一层的节点,并将它们的值添加到对应层的列表中。递归函数 help 接收三个参数:node 表示当前节点,level 表示当前层的层号,levels 表示存储每一层节点值列表的列表。

递归函数的主要逻辑:

如果当前节点为空(即 not node),则直接返回,结束递归。这是递归的终止条件。
如果 len(levels) 等于 level,说明当前层还没有在 levels 中创建一个空列表,所以在 levels 中添加一个新的空列表,用于存储当前层的节点值。
将当前节点的值添加到对应层的列表中。
递归调用 help 处理左子节点,层号加一。
递归调用 help 处理右子节点,层号加一。
通过递归的方式,这个方法遍历整个二叉树,按照层序将节点值存储在 levels 中,最终返回这个列表,完成了层序遍历的任务。

class TreeNode(object):
     def __init__(self, val=0, left=None, right=None):
         self.val = val
         self.left = left
         self.right = right
class Solution(object):
    def levelOrder(self, root):
        levels=[]  # 定义一个空列表用于存储每一层的节点
        self.help(root,0,levels)
        return levels

    def help(self,node,level,levels):
        if not node:
            return
        if len(levels)==level:  # level是节点所在的层,根节点的层数为0
            levels.append([])
        levels[level].append(node.val)
        self.help(node.left,level+1,levels)
        self.help(node.right,level+1,levels)
        

226.翻转二叉树

想要翻转它,其实就把每一个节点的左右孩子交换一下就可以了 

递归三步曲:

  1. 确定递归函数的参数和返回值
  2. 确定终止条件:当节点为空时,就返回
  3. 确定单层递归的逻辑

 这道题用前序遍历和后序遍历解都可以,但是不能用中序遍历,因为中序遍历是左中右:先把左子树翻转,然后左子树和右子树换位置,接下来处理的右子树其实是第一步已经处理过的左子树,所以用中序遍历的话还有点绕。

前序遍历(递归):

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution(object):
    def invertTree(self, root):  # 这里的root其实是指节点,不单单指根节点
        if not root:
            return None
        root.left,root.right=root.right,root.left
        self.invertTree(root.left)
        self.invertTree(root.right)
        return root
        

后序遍历(递归):

class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution(object):
    def invertTree(self, root):  # 这里的root指的是节点,不单指根节点
        if not root:
            return None
        self.invertTree(root.left)
        self.invertTree(root.right)
        root.left,root.right=root.right,root.left
        return root
        

101.对称二叉树

判断一个二叉树是否对称,其实就是判断左右子树是否能够相互翻转(左子树的左孩子和右子树的右孩子是否相等,左子树的右孩子和右子树的左孩子是否相等)

凡是题需要收集子节点的信息返回给父节点的,都采用后序遍历 

递归三步曲:

1.确定递归函数的参数和返回值

因为要比较的是根节点的两个子树是否是相互翻转的,进而判断这个树是不是对称树,所以要比较的是两个树,参数自然也是左子树节点和右子树节点。

返回值自然是bool类型。

2.确定终止条件

要比较两个节点数值相不相同,首先要把两个节点为空的情况弄清楚!否则后面比较数值的时候就会操作空指针了。

节点为空的情况有:(注意我们比较的其实不是左孩子和右孩子,所以如下称之为左节点右节点

  • 左节点为空,右节点不为空,不对称,return false
  • 左不为空,右为空,不对称 return false
  • 左右都为空,对称,返回true

此时已经排除掉了节点为空的情况,那么剩下的就是左右节点不为空:

  • 左右都不为空,比较节点数值,不相同就return false

此时左右节点不为空,且数值也不相同的情况我们也处理了

3.确定单层递归的逻辑

此时才进入单层递归的逻辑,单层递归的逻辑就是处理 左右节点都不为空,且数值相同的情况。

  • 比较二叉树外侧是否对称:传入的是左节点的左孩子,右节点的右孩子。
  • 比较内侧是否对称,传入左节点的右孩子,右节点的左孩子。
  • 如果左右都对称就返回true ,有一侧不对称就返回false 。
class Solution:
    def isSymmetric(self, root):
        if not root:
            return True
        return self.compare(root.left, root.right)
        
    def compare(self, left, right):
        #首先排除空节点的情况
        if left == None and right != None: return False
        elif left != None and right == None: return False
        elif left == None and right == None: return True
        #排除了空节点,再排除数值不相同的情况
        elif left.val != right.val: return False
        
        #此时就是:左右节点都不为空,且数值相同的情况
        #此时才做递归,做下一层的判断
        outside = self.compare(left.left, right.right) #左子树:左、 右子树:右
        inside = self.compare(left.right, right.left) #左子树:右、 右子树:左
        isSame = outside and inside #左子树:中、 右子树:中 (逻辑处理)
        return isSame

 

 

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值