查看: 7308| 回复: 15
跳转到指定楼层
上一主题 下一主题
收起左侧

[树/链表/图] 分享一下自己写binary tree的感悟

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
https://www.1point3acres.com/bbs/thread-542250-1-1.html是这个帖子的后续。因为补充只能有200个字太烦了所以新发一帖。

总结了一下发现其实binary tree蛮常规的。就是有时候用全局pointer变来变去可以降低复杂度有点绕。分享一下也当作练习了。

首先必备的三种recursion方式,也可以看到pre,in,post都是针对于visit root的顺序来定义的。对于inorder,如果是BST的话, 得到的是ascending order的。这一点比较重要。在convert sorted result to bst can be very useful (leetcode 109)

def preorder(root):                           def inorder(root):                                def postorder(root):
visit(root.val)                                    inorder(root.left)                                  postorder(root.left)
preorder(root.left)                             visit(root.val)                                       postorder(root.right)
preorder(root.right)                           inorder(root.right)                                visit(root.val)

然后iterative,都要用到stack. postorder最好利用inorder小改的方式写。不然我们要记录回溯到root的方式。(不能root,root.right root这种循环。所以要用一个数组记录visited root)
def preorder(root):                           def inorder(root):                               def postorder(root):                                       *** recommend  def postorder(root):
stack=[root]                                      stack=[]                                             visited,stack=set(),[]                                        stack=[root]
while(stack):                                     while(stack or root):                             while(stack or root):                                         while(stack):
   node=stack.pop()                               while(root):                                          while(root):                                                   node=stack.pop()
   visit(node)                                             stack.append(root)                               stack.append(root)                                      visit(node)
   if node.right:                                          root=root.left                                      root=root.left                                              if node.left:
      stack.append(node.right)                 node=stack.pop()                                  node=stack.pop()                                              stack.append(node.left)
   if node.left:                                       visit(node)                                             if node.right and not node.right in visited:        if node.right:
     stack.append(node.left)                    root=node.right                                        stack.append(node)                                        stack.append(node.right)
                                                                                                                         root=node.right
                                                                                                                      else:
                                                                                                                          visited.add(node)
                                                                                                                          visit(node)
                                                                                                                          root=None
leetcode 109, 简单的recursion要nlogn的复杂度。因为每次我们要找到中间点。换成array进行处理,虽然复杂度降下来了但是会有额外的空间复杂度。如果我们用global variable记录我们traverse的状态,再结合inorder 得到有序数组的性质,就是很优解啦。

n=def getsize(head):->get the size of the lincked list
def help(l,r):
if l>r:
   return
mid=(l+r)/2
left=help(l,mid-1)    先记录往左边走的node
root=TreeNode(head.val)  左边走完了,现在我们在head点
head=head.next      要往下走了,拿着小本本再走一步
root.right=help(mid+1,r)
root.left=left
return root

这种写法,就是坚信left一定是我们处理完的点(相信自己~~),然后我们带着小本本一定站在了正确的点(head是我们处理好的点)最后我们带着小本本往下走。
再来看用这种方式写leetcode99.如果不用morris traversal,用pred记录上一个visit的点。
standard inorder iterative:
stack=[]
first,second,pred=None,None,None
while (stack or root):
  while(root):
    stack.append(root)
    root=root.left
  node=stack.pop()
  if pre.val<node.val:
     ....
  pre=node
  root=node.right
现在看来,一般对于有序+bt,inorder有得天独厚的优势,所以看见了就想想我们需要一个全局变量。但是,全局变量就像中央空调,(鄙视),一般能不用就不用,其他的题都可以用常规的递归解决。
今天又是开心的刷题的一天尼~







                                                                       





补充内容 (2019-8-13 08:53):
postorder traversal忘记写return res[::-1]啦?补充一下。。https://leetcode.com/problems/binary-tree-postorder-traversal/

评分

参与人数 7大米 +86 收起 理由
sawadevil + 1 很有用的信息!
oliviapanh + 1 赞一个
mwang011 + 1 赞一个
jackchen823 + 1 给你点个赞!
Carofish + 1 很有用的信息!

查看全部评分


上一篇:地里小萌新来报道,刷leetcode被打击了,准备从基础算法看起,推荐一本基础入门算法书
下一篇:希望这个帖子能帮到跟以前的我一样惧怕DFS BFS题目的同学
推荐
 楼主| 咸鱼也有春天 2019-8-12 03:41:06 | 只看该作者
全局:
provhomme 发表于 2019-8-12 02:44
我感觉你的recommended post order不太对啊

你是说没有写return res[::-1]咩?忘记写了。。。https://leetcode.com/problems/binary-tree-postorder-traversal/
回复

使用道具 举报

推荐
provhomme 2019-8-12 02:44:22 | 只看该作者
全局:
我感觉你的recommended post order不太对啊
回复

使用道具 举报

推荐
torez 2019-8-12 08:36:37 | 只看该作者
全局:
本帖最后由 torez 于 2019-8-12 08:53 编辑

楼主,post-order traversal 没必要keep track of all visited node吧,一个prev就足够了,这是我常用的写法
def postorder_traversal(root)
    return [] unless root
   
    rst, stack, curr, prev = [], [], root, nil
   
    while stack.any? || curr
        while curr
            stack << curr
            curr = curr.left
        end
        
        top = stack[-1]
        if top.right && prev != top.right
            curr = top.right
        else
            stack.pop()
            rst.push << top.val
            prev = top
        end
    end
    rst
end


评分

参与人数 1大米 +2 收起 理由
咸鱼也有春天 + 2 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
lindashu 2019-8-11 14:58:24 | 只看该作者
本楼:
全局:
顶一下lz
回复

使用道具 举报

🔗
337845818 2019-8-12 04:17:23 | 只看该作者
全局:
树只是一种特殊的图, 图学明白就好

visiting order并不重要,基本上pre order和in order就够了

评分

参与人数 1大米 +1 收起 理由
咸鱼也有春天 + 1 很有用的信息!

查看全部评分

回复

使用道具 举报

🔗
provhomme 2019-8-12 04:55:30 | 只看该作者
全局:
linqiuli 发表于 2019-8-12 03:41
你是说没有写return res[::-1]咩?忘记写了。。。https://leetcode.com/problems/binary-tree-postorder- ...

我觉得这样并没有按照post order来traverse一个树,虽然这样倒序输出list是正确的答案。但如果面试官要求print出节点就不行了。

评分

参与人数 1大米 +1 收起 理由
咸鱼也有春天 + 1 给你点个赞!

查看全部评分

回复

使用道具 举报

🔗
alexan0218 2019-8-12 06:05:47 | 只看该作者
全局:
provhomme 发表于 2019-8-11 13:44
我感觉你的recommended post order不太对啊

少写了一步 return 的时候把结果反过来
回复

使用道具 举报

🔗
 楼主| 咸鱼也有春天 2019-8-12 09:49:34 | 只看该作者
全局:
torez 发表于 2019-8-12 08:36
楼主,post-order traversal 没必要keep track of all visited node吧,一个prev就足够了,这是我常用的写 ...

你这个不错诶。点赞!
回复

使用道具 举报

🔗
 楼主| 咸鱼也有春天 2019-8-12 09:51:26 | 只看该作者
全局:
provhomme 发表于 2019-8-12 04:55
我觉得这样并没有按照post order来traverse一个树,虽然这样倒序输出list是正确的答案。但如果面试官要求 ...

嗯,还是要看面试官的要求
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表