【LetMeFly】102.二叉树的层序遍历 + 针对C++的使用空间优化 (可能不同于常规做法) 力扣题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/
给你二叉树的根节点 root
,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。
示例 1:
输入: root = [3,9,20,null,null,15,7]
输出: [[3],[9,20],[15,7]]
示例 2:
输入: root = [1]
输出: [[1]]
示例 3:
输入: root = []
输出: []
提示:
树中节点数目在范围 [0, 2000]
内
-1000 <= Node.val <= 1000
方法一:层次遍历 记根节点为第$0$层
我们用pair<TreeNode*, int>
记录<此节点, 此节点的层数>
初始时将根节点入队,在队列不空的时候:
不断取出队首元素,如果此元素不空,就判断此元素和上一个元素是否在同一层
如果不在同一层,就把上一层的所有节点添加到答案中
把此节点的左右子入队(层数=此层+1)
详见代码注释。
时间复杂度$O(N)$,其中$N$是节点个数
空间复杂度$O(N2)$,其中$N2$是节点最多的一层的节点数
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 typedef pair<TreeNode*, int > pii;class Solution {public : vector<vector<int >> levelOrder (TreeNode* root) { if (!root) return {}; queue<pii> q; int lastLayer = 0 ; q.push ({root, 0 }); vector<vector<int >> ans; vector<int > thisAns; while (q.size ()) { auto [p, thisLayer] = q.front (); q.pop (); if (!p) continue ; if (thisLayer != lastLayer) { lastLayer = thisLayer; ans.push_back (thisAns); thisAns.clear (); } thisAns.push_back (p->val); q.push ({p->left, thisLayer + 1 }); q.push ({p->right, thisLayer + 1 }); } ans.push_back (thisAns); return ans; } };
方法二:层次遍历 + 针对C++的使用空间优化 不难发现,方法一中,vector<int> thisAns
用来记录这一层的节点。
当遇到新的一层的节点时,我们将````thisAnspush到了
ans中,然后将
thisAns```清空。
通俗地讲,就是先copy
后删除
。也许上述现象在某些语言中并不会发生,但C++中,确实会先为ans
申请一些新的空间,再释放掉thisAns
的空间,而不是直接让ans
的下一个元素指向thisAns
。
那么,我们如何避免上述现象呢?也很简单,只需要在ans
中提前开辟一层,并且使用ans[ans.size() - 1]
代替thisAns
即可。
时间复杂度$O(N)$,其中$N$是节点个数。与方法一相比,不需要专门将“某一层”添加到答案中,也不需要清空“用于存储某一层的空间”
空间复杂度$O(N2)$,其中$N2$是节点最多的一层的节点数。与方法一相比,优势在于没有专门为某一层申请临时存储空间
上述优化仅仅是个小优化,并不会改变复杂度。
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 typedef pair<TreeNode*, int > pii;class Solution {public : vector<vector<int >> levelOrder (TreeNode* root) { if (!root) return {}; int lastLayer = 0 ; queue<pii> q; q.push ({root, 0 }); vector<vector<int >> ans; ans.push_back ({}); while (q.size ()) { auto [p, thisLayer] = q.front (); q.pop (); if (!p) continue ; if (thisLayer != lastLayer) { lastLayer = thisLayer; ans.push_back ({}); } ans[thisLayer].push_back (p->val); q.push ({p->left, thisLayer + 1 }); q.push ({p->right, thisLayer + 1 }); } return ans; } };
方法三:更简单点的方法(不需要将“那一层”的信息入队) 我们只需要将节点入队,当队列非空时:
假如当前队列的大小为$size$,那么就一共循环$size$次,并作为一层加入到答案中。
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : vector<vector<int >> levelOrder (TreeNode* root) { vector<vector<int >> ans; queue<TreeNode*> q; if (root) { q.push (root); } while (q.size ()) { ans.push_back ({}); for (int i = q.size (); i > 0 ; i--) { TreeNode* thisNode = q.front (); q.pop (); ans.back ().push_back (thisNode->val); if (thisNode->left) { q.push (thisNode->left); } if (thisNode->right) { q.push (thisNode->right); } } } return ans; } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class Solution : def levelOrder (self, root: Optional [TreeNode] ) -> List [List [int ]]: ans = [] q = [] if root: q.append(root) while q: ans.append([]) for _ in range (len (q)): thisNode = q[0 ] q = q[1 :] ans[-1 ].append(thisNode.val) if thisNode.left: q.append(thisNode.left) if thisNode.right: q.append(thisNode.right) return ans
时间复杂度$O(N)$,其中$N$是节点个数
空间复杂度$O(N2)$,其中$N2$是节点最多的一层的节点数
同步发文于CSDN,原创不易,转载请附上原文链接 哦~ Tisfy:https://letmefly.blog.csdn.net/article/details/125584554