1.数据结构-树问题

前后中遍历-非递归写法

中序遍历稍微难一些,第二种写法不太好想出来

94. 二叉树的中序遍历

def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return None
        # 中序遍历写法1
        stack,ans = [root,],[]
        while(stack):
            while(root.left):
                stack.append(root.left)
                root = root.left
            node = stack.pop()
            ans.append(node.val)
            if node.right:
                stack.append(node.right)
                root = node.right
        # 中序遍历写法2 -> 写法1的升级写法,不需要赋值临时节点
        stack,ans = [],[]
        while(stack or root):
            while(root):
                stack.append(root)
                root = root.left
            root = stack.pop()
            ans.append(root.val)
            root = root.right

        return ans

中序遍历的应用
验证二叉搜索树,保底写法:遍历之后放到数组中,然后判断数组是否严格升序

98. 验证二叉搜索树

def isValidBST(self, root: TreeNode) -> bool:
        if not root: return True
        # 掌握中序法1写法
        stack,inorder = [root,],float('-inf')
        while(stack):
            while(root.left):
                stack.append(root.left)
                root = root.left
            node = stack.pop()
            if node.val <= inorder: return False
            inorder = node.val
            if(node.right):
                stack.append(node.right)
                root = node.right
        return True
        # 掌握中序法2写法
        stack, inorder = [], float('-inf')
        while stack or root:
            while root:
                stack.append(root)
                root = root.left
            root = stack.pop()
            if root.val <= inorder:
                return False
            inorder = root.val
            root = root.right
        return True

590. N叉树的后序遍历

class Solution:
    def postorder(self, root: 'Node') -> List[int]:
        if root is None:
            return []
        stack, res = [root, ], []
        while(stack):
            root = stack.pop()
            if(root is not None):
                res.append(root.val)
            for child in root.children:
                stack.append(child)
        return res[::-1]

BFS&层次遍历

使用队列,把每个还没有搜索到的点依次放入队列,然后再弹出队列的头部元素当做当前遍历点。BFS总共有两个模板:

如果不需要确定当前遍历到了哪一层,BFS模板如下。

while queue 不空:
    cur = queue.pop()
    for 节点 in cur的所有相邻节点:
        if 该节点有效且未访问过:
            queue.push(该节点)

如果要确定当前遍历到了哪一层,BFS模板如下。
这里增加了level表示当前遍历到二叉树中的哪一层了,也可以理解为在一个图中,现在已经走了多少步了。size表示在当前遍历层有多少个元素,也就是队列中的元素数,我们把这些元素一次性遍历完,即把当前层的所有元素都向外走了一步。

level = 0
while queue 不空:
    size = queue.size()
    while (size --) {
        cur = queue.pop()
        for 节点 in cur的所有相邻节点:
            if 该节点有效且未被访问过:
                queue.push(该节点)
    }
    level ++;

BFS经典例题1 - 129. 求根到叶子节点数字之和

思路:维护两个队列,一个是正常用的存储节点的,一个是节点的值方便用来做计算

def sumNumbers(self, root: TreeNode) -> int:
        if not root: return 0
        from collections import deque
        q1,q2 = deque([root]),deque([root.val]) 
        res = 0
        while(q1):
            node = q1.popleft()
            v = q2.popleft()
            l,r = node.left, node.right
            if l:
                q1.append(l)
                q2.append(v*10+l.val)
            if r:
                q1.append(r)
                q2.append(v*10+r.val)
            if not l and not r:
                res+=v
        return res

BFS经典例题2 - 116. 填充每个节点的下一个右侧节点指针

class Solution:
    def connect(self, root: 'Node') -> 'Node':
        if not root:
            return None
        from collections import deque 
        q=deque([root])  
        while(q):
            size = len(q)
            for i in range(size):
                node = q.popleft()
                if i == size - 1:
                    node.next = None
                else:
                    node.next = q[0] #deque支持通过下标取元素
                if node.left:
                    q.append(node.left)
                if node.right:
                    q.append(node.right)
        return root

BFS经典例题 3 -127. 单词接龙

def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
        size = len(beginWord)
        dic = defaultdict(list)
        for word in wordList:
            for i in range(size):
                key = word[:i]+"*"+word[i+1:]
                dic[key].append(word)
        from collections import deque
        q = deque()
        q.append((beginWord,1))
        visited = defaultdict(bool)
        visited[beginWord] = True
        while q:
            current_word,level = q.popleft()
            size = len(current_word)
            for i in range(size):
                key = current_word[:i]+'*'+current_word[i+1:]
                for neighour in dic[key]:
                    if neighour == endWord:
                        return level+1
                    if not visited[neighour]:
                        visited[neighour] = True
                        q.append((neighour,level+1))
        return 0

BFS经典例题4 - N叉树的层次遍历

def levelOrder(self, root: 'Node') -> List[List[int]]:
        if not root: return root
        d = collections.deque()
        d.append(root)
        res = []
        while d :
            n = len(d)
            tmp = []
            for i in range(n):
                node = d.popleft()
                tmp.append(node.val)
                if node.children:
                    d.extend(node.children)
            res.append(tmp)
        return res

递归遍历

面试题 04.02. 最小高度树

自己的代码

def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
    if(len(nums)==0):
        return None
    mid = len(nums) // 2
    root = TreeNode()
    root.val = nums[mid]
    root.left = self.sortedArrayToBST(nums[0:mid])
    root.right = self.sortedArrayToBST(nums[mid+1:len(nums)])
    return root

下面是标准答案,可以看到一些细节上的差异

def sortedArrayToBST(self, nums: List[in]) -> TreeNode:
    if not len(nums):  return
    mid = len(nums) // 2
    root = TreeNode(nums[mid])
    root.left = self.sortedArrayToBST(nums[: mid]) 
    root.right = self.sortedArrayToBST(nums[mid + 1: ])
    return root 

其他一些树的问题

二叉树深度

def maxDepth(self, root: TreeNode) -> int:
        if(root is None):
            return 0
        elif(root.left is None and root.right is None):
            return 1
        else :
            return max(self.maxDepth(root.left), self.maxDepth(root.right)) + 1

二叉树镜像-递归

def mirrorTree(self, root: TreeNode) -> TreeNode:
        if(root is None):
            return 
        else:
            root.left, root.right = root.right, root.left
            self.mirrorTree(root.left)
            self.mirrorTree(root.right)
        return root

二叉搜索树所有节点值的和-递归

def rangeSumBST(self, root: TreeNode, L: int, R: int) -> int:
        if(root is None):
            return 0
        elif(root.val>=L and root.val<=R):
            l,r = 0,0
            if(root.left):
                l = self.rangeSumBST(root.left,L,R)
            if(root.right):
                r = self.rangeSumBST(root.right,L,R)
            return root.val + l + r

二叉树合并

def mergeTrees(self, t1: TreeNode, t2: TreeNode) -> TreeNode:   
    if(not t1 and not t2):
        return None
    elif(t1 and not t2): 
        return t1
    elif(t2 and not t1):
        return t2
    else:
        t = TreeNode() 
        t.val = t1.val + t2.val
        t.left = self.mergeTrees(t1.left, t2.left)
        t.right = self.mergeTrees(t1.right, t2.right)
        return t

1.589. N叉树的前序遍历

def preorder(self, root: 'Node') -> List[int]:
       res = []
       def helper(root):
           if not root:
               return
           res.append(root.val)
           for child in root.children:
               helper(child)
       helper(root)
       return res

2. 108. 将有序数组转换为二叉搜索树

这个树的也不会

def sortedArrayToBST(self, nums: List[int]) -> TreeNode:
        def helper(left, right):
            if left > right:
                return None

            # 总是选择中间位置左边的数字作为根节点
            mid = (left + right) // 2

            root = TreeNode(nums[mid])
            root.left = helper(left, mid - 1)
            root.right = helper(mid + 1, right)
            return root

        return helper(0, len(nums) - 1)

下面的456分别是二叉树的三个遍历,重新复习一下吼吼吼

class Solution:
     # 前序遍历 根左右 让右边的后弹出,所以右边的要先压栈
    def preorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return None
        stack,ans = [root],[]
        while(stack):
            tmp = stack.pop()
            ans.append(tmp.val)
            if tmp.right:
                stack.append(tmp.right)
            if tmp.left:
                stack.append(tmp.left)
        return ans
  # 后序遍历 左右根 相当于根右左 然后取反就行 让左边的后弹出,所以左边的先压栈
  def postorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return None
        stack,ans = [root],[]
        while(stack):
            tmp = stack.pop()
            ans.append(tmp.val)
            if tmp.left:
                stack.append(tmp.left)
            if tmp.right:
                stack.append(tmp.right)
        return ans[::-1]
# 中序遍历 先把左节点全部入栈 弹出过程中查看是否有右节点
def inorderTraversal(self, root: TreeNode) -> List[int]:
        if not root:
            return None
        stack, ans = [root,],[]
        while(stack):
            while root.left:    
                stack.append(root.left)  
                root = root.left
            node = stack.pop()
            ans.append(node.val)
            if(node.right):
                stack.append(node.right)
                root = node.right
        return ans

1. 199. 二叉树的右视图

def rightSideView(self, root: TreeNode) -> List[int]:
        dic = {}
        max_depth = -1
        stack = [(root,0)]
        while(stack):
            #每次先弹出的是右边节点的值
            #没有右边节点就会弹出左边的,都没有表示没有节点了
            node, depth = stack.pop()
            if (node):
                max_depth = max(max_depth,depth)
                dic[depth] = dic.setdefault(depth,node.val)
                # 下面这两行代码换一下就可以从右视图变成左视图
                stack.append((node.left,depth+1))
                stack.append((node.right,depth+1))
        return list(dic.values())
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,588评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,456评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,146评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,387评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,481评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,510评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,522评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,296评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,745评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,039评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,202评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,901评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,538评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,165评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,415评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,081评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,085评论 2 352