二叉树的层序遍历及变体

  1. 层序遍历
    知识点:python3的deque:https://blog.csdn.net/langb2014/article/details/100118296
    模板:
    popleft一个节点,append自己的value到level数组中(遍历该层),然后append所有他的子节点到queue中(queue存下一层的节点);将一层的节点都popleft后,将level数组存入res数组(将该层节点值加入结果数组)。

python:

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

class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        queue = collections.deque()
        if root:
        	queue.append(root)
        res = []
        while queue:
            size = len(queue)
            level = []
            for _ in range(size):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                	queue.append(cur.left)
                if cur.right:
                	queue.append(cur.right)
            res.append(level)
        return res


c++

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != NULL) que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {
            int size = que.size();
            vector<int> vec;
            // 这里一定要使用固定大小size,不要使用que.size(),因为que.size是不断变化的
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left) que.push(node->left);
                if (node->right) que.push(node->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};


  1. 二叉树的层次遍历 II
    给定一个二叉树,返回其节点值自底向上的层次遍历。最后用res.reverse()或者reversed_res = reversed(res)把result数组反转一下就可以了。
    Note:reversed()可作用于各种可迭代对象,返回 list_reverseiterator object对象,可用list()转换为list对象。list.reverse()是原地转换,改变原数组。sorted()返回将迭代器中的元素排序的新列表
class Solution(object):
    def levelOrder(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        queue = collections.deque()
        if root:
        	queue.append(root)
        res = []
        while queue:
            size = len(queue)
            level = []
            for _ in range(size):
                cur = queue.popleft()
                level.append(cur.val)
                if cur.left:
                	queue.append(cur.left)
                if cur.right:
                	queue.append(cur.right)
            res.append(level)
        res.reverse()     # 反转res    
        return res

199.二叉树的右视图

给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。

层序遍历的时候,判断是否遍历到单层的最后面的元素,如果是,就放进result数组中,随后返回result就可以了。

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: TreeNode) -> List[int]:
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        queue = collections.deque()
        if root:
            queue.append(root)
        res = []
        while queue:
            size = len(queue)
            
            for i in range(size):
                cur = queue.popleft()
                if i == size - 1: # 判断是否遍历到单层的最后面的元素
                	res.append(cur.val)
                if cur.left:
                    queue.append(cur.left)
                if cur.right:
                    queue.append(cur.right)
            
        return res

637.二叉树的层平均值

给定一个非空二叉树, 返回一个由每层节点平均值组成的数组。本题就是层序遍历的时候把一层求个总和在取一个均值。

class Solution(object):
    def averageOfLevels(self, root):
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        queue = collections.deque()
        if root:
        	queue.append(root)
        res = []
        while queue:
            size = len(queue)
            sum = 0
            for i in range(size):
                cur = queue.popleft()
                sum += cur.val;
                if cur.left:
                	queue.append(cur.left)
                if cur.right:
                	queue.append(cur.right)
            res.append(sum / size); # 将每一层均值放进结果集
        return res
  1. N叉树的层序遍历
"""
# Definition for a Node.
class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children
"""

class Solution:
    def levelOrder(self, root: 'Node') -> List[List[int]]:
        """
        :type root: TreeNode
        :rtype: List[List[int]]
        """
        queue = collections.deque()
        if root:
        	queue.append(root)
        res = []
        while queue:
            size = len(queue)
            level = []
            for _ in range(size):
                cur = queue.popleft()

                level.append(cur.val)
                for children in cur.children:
                    if children:
                        queue.append(children)
            res.append(level)
        return res
  1. 在每个树行中找最大值
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def largestValues(self, root: TreeNode) -> List[int]:
        queue = collections.deque()
        if root:
        	queue.append(root)
        res = []
        while queue:
            size = len(queue)
            max_val = float("-inf")
            for _ in range(size):
                cur = queue.popleft()
                if max_val < cur.val:
                    max_val = cur.val
                if cur.left:
                	queue.append(cur.left)
                if cur.right:
                	queue.append(cur.right)
            res.append(max_val)
        return res
  1. 填充每个节点的下一个右侧节点指针 - 完美二叉树(满二叉树)

https://leetcode-cn.com/problems/populating-next-right-pointers-in-each-node/solution/dong-hua-yan-shi-san-chong-shi-xian-116-tian-chong/

1)时间空间复杂度都为O(N)的解法,借助层序遍历:
本题依然是层序遍历,只不过在单层遍历的时候记录一下本层的头部节点,然后在遍历的时候让前一个节点指向本节点就可以了.

"""
# Definition for a Node.
class Node:
    def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
        self.val = val
        self.left = left
        self.right = right
        self.next = next
"""
class Solution:
	def connect(self, root: 'Node') -> 'Node':
		"""
		:type root: Node
		:rtype: Node
		"""
		queue = []
		if root:
			queue.append(root)
		else:
			return root
		while queue:
			size = len(queue)
			# 将队列中的元素串联起来
			tmp = queue[0]
			for i in range(1,size):
				tmp.next = queue[i]
				tmp = queue[i]
			# 遍历队列中的每个元素,将每个元素的左右节点也放入队列中
			for _ in range(size):
				tmp = queue.pop(0)
				if tmp.left:
					queue.append(tmp.left)
				if tmp.right:
					queue.append(tmp.right)
		return root

2)时间空间复杂度为O(N)、O(1)的解法,不需要额外空间

在这里插入图片描述

有两种情况,一种是两个串联的节点都有一个共同的父节点,通过父节点就可以将这两个子节点串联起来;一种是两个串联的节点的父节点不同,对于这种情况,如果我们能将这一层的上一层串联好。那么可以通过父节点的next找到邻居,完成串联。

通过操作pre指针和tmp指针,pre指向每一层的第一个节点,tmp指向这一层的每一个节点,将所有下一层的节点都连接起来。

class Solution(object):
	def connect(self, root):
		"""
		:type root: Node
		:rtype: Node
		"""
		if not root:
			return root
		pre = root
		# 循环条件是当前节点的left不为空,当只有根节点
		# 或所有叶子节点都出串联完后循环就退出了
		while pre.left:
			tmp = pre
			while tmp:
				# 将tmp的左右节点都串联起来
				# 注:外层循环已经判断了当前节点的left不为空
				tmp.left.next = tmp.right
				# 下一个不为空说明上一层已经帮我们完成串联了
				if tmp.next:
					tmp.right.next = tmp.next.left
				# 继续右边遍历
				tmp = tmp.next
			# 从下一层的最左边开始遍历	
			pre = pre.left
		return root


3)时间空间复杂度分别为O(N)、O(h)的递归解法,h是树的高度

上面两种方式利用层序遍历,属于横向的视角,而递归则像是一个深度的视角。

我们以当前节root点为起始,左右节点不断的深入下面,left节点不断往右走,right节点不断往左走,当这两个节点走到底后,整个纵深这段就完成了串联。
在这里插入图片描述

递归函数实现如下:

终止条件:当前节点为空时
函数内:以当前节点为起始,完成从上往下的纵深串联,再递归的调用当前节点left和right

在这里插入图片描述

class Solution(object):
	def connect(self, root):
		"""
		:type root: Node
		:rtype: Node
		"""
		def dfs(root):
			# 停止条件
			if not root:
				return
			# 完成以root为起点的整个纵深串联
			left = root.left
			right = root.right
			while left:
				left.next = right
				left = left.right
				right = right.left
			# 递归的调用左右节点,完成同样的纵深串联
			dfs(root.left)
			dfs(root.right)
		dfs(root)
		return root


  1. 填充每个节点的下一个右侧节点指针 II - 非完美二叉树
class Solution:
	def connect(self, root: 'Node') -> 'Node':
		"""
		:type root: Node
		:rtype: Node
		"""
		queue = []
		if root:
			queue.append(root)
		else:
			return root
		while queue:
			size = len(queue)
			# 将队列中的元素串联起来
			tmp = queue[0]
			for i in range(1,size):
				tmp.next = queue[i]
				tmp = queue[i]
			# 遍历队列中的每个元素,将每个元素的左右节点也放入队列中
			for _ in range(size):
				tmp = queue.pop(0)
				if tmp.left:
					queue.append(tmp.left)
				if tmp.right:
					queue.append(tmp.right)
		return root
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值