【问题标题】:Zigzag level order traversal之字形水平顺序遍历
【发布时间】:2018-08-17 06:14:38
【问题描述】:

我正在尝试在https://www.interviewbit.com/problems/zigzag-level-order-traversal-bt/ 上对二叉树的节点值进行锯齿形级别顺序遍历(即,从左到右,然后从右到左进行下一级并在其间交替)但是编译器给出了超出时间限制错误。我该如何解决?

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

class Solution:
    # @param A : root node of tree
    # @return a list of list of integers
    def zigzagLevelOrder(self, A):
        st_crt_lvl =[A]
        st_nxt_lvl =[]
        ans_list = []

        while st_crt_lvl:
            u = st_crt_lvl.pop(0)
            ans_list.append(u.val) 
            if u.left:
                st_nxt_lvl.append(u.left)
            if u.right:
                st_nxt_lvl.append(u.right)
            while st_nxt_lvl:
                u = st_nxt_lvl.pop()
                ans_list.append(u.val)

                if u.right:
                    st_crt_lvl.append(u.right)
                if u.left:
                    st_crt_lvl.append(u.left)


        return ans_list

【问题讨论】:

    标签: python algorithm data-structures binary-tree graph-algorithm


    【解决方案1】:

    您可以从代码中消除多个内部while 循环,方法是使队列st_nxt_lvl 成为临时队列,并将此临时队列的内容复制到当前队列st_crt_lvl,在每个级别的二叉树处理结束时.

    这可以通过只保留一个队列(没有任何临时存储)和标准bfs 算法的级别顺序遍历来实现,但是由于我们希望在每个级别上进行锯齿形顺序遍历,因此使用临时的更优雅队列,这样临时队列只保留下一级元素,当当前级元素处理完成时,当前队列指向下一级。

    对您的代码进行一些修改,并附上示例树:

    def zigzagLevelOrder(A):
    
        st_crt_lvl = [A] # initialize
        ans_list = []   
    
        level = 0
        while st_crt_lvl: # check if all levels are processed
            st_nxt_lvl =[] # temporary queue to hold the next level elements
            tmp = [] # temporary storage to append to the ans_list 
            while st_crt_lvl:
                u = st_crt_lvl.pop(0)
                tmp.append(u.val) 
                if u.left:
                    st_nxt_lvl.append(u.left)
                if u.right:
                    st_nxt_lvl.append(u.right)                
            if (len(tmp) > 0): # if tmp is not empty
                if level % 2 == 1: # ensure zig-zag level order traversal
                    tmp = tmp[::-1]
                ans_list.append(tmp)
            st_crt_lvl = st_nxt_lvl  # copy the temporary queue to the current queue      
            level += 1
    
        return ans_list
    
    
    class BinaryTree:
        def __init__(self, left, right, data):
            self.left = left
            self.right = right
            self.val = data
    
    A = BinaryTree(None, None, 3)
    A.left = BinaryTree(None, None, 9)
    A.right = BinaryTree(None, None, 20)
    A.left.left = BinaryTree(None, None, 1)
    A.left.right = BinaryTree(None, None, 2)
    A.right.left = BinaryTree(None, None, 15)
    A.right.right = BinaryTree(None, None, 7)
    zigzagLevelOrder(A)
    # [[3], [20, 9], [1, 2, 15, 7]]
    

    【讨论】:

    • 如果你解释一下你在这里做了什么,这个答案会更有帮助。您似乎很明显,您只需进行分配就消除了将元素从“下一个”堆栈复制到“当前”堆栈,但 OP 可能不完全理解它是如何工作的或为什么它更快。
    • 当然我会添加解释
    【解决方案2】:

    您可以使用广度优先搜索:

    from collections import deque, defaultdict
    class Tree:
      def __init__(self, **kwargs):
        self.__dict__ = {i:kwargs.get(i) for i in ['left', 'right', 'value']}
      def __contains__(self, _val):
       if self.value != _val and self.left is None and self.right is None:
         return False
       return True if self.value == _val else any([_val in [[], self.left][self.left is not None], _val in [[], self.right][self.right is not None]])
      def __lookup(self, _val, _depth = 0):
        if self.value == _val:
          return _depth
        return getattr(self, 'left' if _val in self.left else 'right').__lookup(_val, _depth+1)
      def __getitem__(self, _val):
        return self.__lookup(_val)    
    
    def bfs(_head):
      _d = deque([_head])
      _seen = []
      _last = None
      _final_result = defaultdict(list)
      while _d:
       _current = _d.popleft()
       if _current.value not in _seen:
          _seen.append(_current.value)
          _r = list(filter(None, [getattr(_current, i, None) for i in ['left', 'right']]))
          _d.extend(_r)
          _final_result[_head[_current.value]].append(_current.value)
      marker = iter(range(len(_final_result)))
      return [i[::-1] if next(marker)%2 else i for _, i in sorted(_final_result.items(), key=lambda x:x[0])]
    

    当从问题中的链接构造示例中的相同树时,输出为:

    t = Tree(value=3, left=Tree(value=9), right=Tree(value=20, left=Tree(value=15), right=Tree(value=7)))
    print(bfs(t))
    

    输出:

    [[3], [20, 9], [15, 7]]
    

    此解决方案使用breadth-first search 水平遍历树。但是,由于(完整)二叉树有两个孩子,因此只会将两个值添加到队列中。因此,为了确定搜索达到的当前树级别,必须在树中实现一种查找特定值深度的方法(__getitem____lookup)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-13
      • 1970-01-01
      • 2014-06-27
      • 2020-07-16
      • 1970-01-01
      相关资源
      最近更新 更多