二叉树-算法题

前话:

     二叉树的深度优先搜素和广度优先搜索:

1、广度优先搜索(BFS)

     宽度优先搜索写为BFS,其过程检验来说就是对每一层节点依次访问,访问这一层浸润下一层,而且每个节点只能访问一次。对于上面的例子来说,广度优先遍历的结果是:3->9->20->15->7。

     宽度优先遍历各个节点,需要使用队列这种数据结构,queue的特点是先进先出。

     首先将 3 节点插入到队列中,queue(3);

     将3节点弹出,同时将3的子节点9,20插入到队列中去,此时queue(9,20);

     将9节点弹出,9节点没有子节点,然后将20节点弹出,将20节点的子节点插入到队列中去,此时queue(15,7)

     将15节点弹出,15节点没有子节点,将7节点弹出,7节点没有子节点。

     广度优先遍历的结果是:3->9->20->15->7

     我用list代替queue,pop替代queue从队尾插入元素,pop(0)替代从队首弹出元素:

     

class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        queue = [root]
        d = []
        
        while queue:
            tn = queue.pop(0)
            d.append(d)
            if tn and tn.left.val:
                queue.append(tn.left)
            if tn and tn.right.val:
                queue.append(tn.right)
                
        

 2、深度优先搜索

     二叉树的的深度优先遍历有前序、中序和后序三种遍历方法,因为树的定义本身就是递归定义,因此用递归去实现三种遍历方法易理解且比较简洁,三种遍历方法的主要思想为:

     前序遍历:根节点--->左子树--->右子树

     中序遍历:左子树--->根节点--->右子树

     后序遍历:左子树--->右子树--->根节点

(1).前序遍历

      根据前序遍历的思想,我们写出它的递归版本

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrderBottom(self, root: TreeNode):
        if root:
            print(root.val)
            self.levelOrderBottom(root.left)
            self.levelOrderBottom(root.right)
    

     现在写前序遍历的非递归版本,具体思路如下:

     根据前序遍历的思想,我们优先遍历根节点,然后左节点再之后右节点,这里我们用栈这个数据结构,先将根节点压入栈中,然后将根节点弹出,根据栈先进后出的规则,将根节点的右孩子压入栈中,再将左孩子压入栈中,之后将左孩子作为根节点,重复上述这个过程。

     我们以最上面的那个二叉树举例:

     我们首先将3节点压入栈中,此时stack(3);

     将3节点弹出,然后先将3节点的右孩子压入到栈中,再将左孩子压入到栈中,此时stack(20,9);

     将9节点弹出,因为9节点没有孩子节点,所以继续将20节点弹出,再将20节点的右孩子和左孩子分别压入栈中,此时stack(7,15);

     将20节点弹出,15和7节点没有孩子节点,继续弹出15节点和7节点;

      所以先序遍历的结果是:3->9->20->15->7

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrderBottom(self, root: TreeNode):
        a = [root]
  

        while a:
            c = a.pop()
            print(c)

            if c.right:
                a.append(c.right)
            if  c.left:
                a.append(c.left)

(2).中序遍历

     根据中序遍历的思思想,我们写出它的递归版本:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrderBottom(self, root: TreeNode):
            self.levelOrderBottom(root.left)
            print(root.val)
            self.levelOrderBottom(root.right)

     现在写中序遍历的非递归版本,具体思路如下:

     根据中序遍历的顺序,优先访问左子树,然后访问根节点和右子树,但是左子树是根据根节点来的,所以对于任意节点,如果非空,直接储存之,然后判断左子树是否为空,不为空重复上述过程,如果为空,我们访问右子树,我们需要使用栈这种数据结构的支持。对于任意一个节点node,具体步骤如下:

     a)访问之,并把节点node入栈,当前节点设置为左孩子;

     b)判断当前节点是否为空,不为空重复上述过程,如果为空,取出栈顶节点并出栈,将右孩子设置为当前节点;否则重复a)步骤直到当前节点为空或者栈为空。

      代码如下:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def levelOrderBottom(self, root: TreeNode) -> List[List[int]]:
        stack = []
        pos = root

        while  pos is not None or stack:
            if pos:
                stack.append(pos)
                pos = pos.left
            else:
                pos = stack.pop()
                print(pos.val)
                pos = pos.right

     

      

 

 

 

     

      

 

 

 

 

题目:来源-leetcode101.对称二叉树 

     递归:

     解体思路:如果两个二叉树镜像对称,那么一个树的左子树和另一个树的右子树镜像对称。

     1.怎么判断一棵树是不是对称二叉树? 答案:如果所给根节点,为空,那么是对称。如果不为空的话,当他的左子树与右子树对称时,他对称。

     2.那么怎么知道左子树与右子树对不对称呢?在这我直接叫为左树和右树 答案:如果左树的左孩子与右树的右孩子对称,左树的右孩子与右树的左孩子对称,那么这个左树和右树就对称。

 

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def ismirror(self,tag1,tag2):
        if not tag1 and not tag2:
            return True
        if not tag1 or not tag2:
            return False
        if tag1.val != tag2.val: #针对第二层的节点
            return False
        return self.ismirror(tag1.left,tag2.right) and  self.ismirror(tag1.right,tag2.left)
    def isSymmetric(self, root: TreeNode) -> bool:
        return self.ismirror(root,root)

     迭代:

     方法1:

     解题思路:分别取出每一次的所有结点的值放入到列表中,然后判断是不是回文数,如果不是,就返回False

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        queue = [root]

        while queue:
            b,c = [],[]

            for i in queue:
                if not i:
                    c.append(None) #防止出现一边是空的二叉树
                    continue
                b.append(i.left)
                b.append(i.right)
                c.append(i.val)
            
            if c != c[::-1]:
                return False
            queue = b
        
        return True

     方法2:

     解题思路:

     除了递归的方法外,我们也可以利用队列进行迭代。队列中每两个连续的结点应该是相等的,而且它们的子树互为镜像。最         初,队列中包含的是 root 以及 root。每次提取两个结点并比较它们的值。然后,将两个结点的左右子结点按相反的顺序插入队列中。当队列为空时,或者我们检测到树不对称(即从队列中取出两个不相等的连续结点)时,该算法结束。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isSymmetric(self, root):
        """
        :type root: TreeNode
        :rtype: bool
        """
        queue = [root,root]

        while queue:
            q1 = queue.pop()
            q2 = queue.pop()

            if not q1 and not q2:
                continue         #当节点部分为None时,需要判断其余部分是否镜像相同
            if not q1 or not q2:
                return False
            
            if q1.val != q2.val:
                return False
            
            queue.append(q1.left)
            queue.append(q2.right)
            queue.append(q1.right)
            queue.append(q2.left)
        
        return True

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值