劍指Offer_#32_從上到下列印二叉樹
阿新 • • 發佈:2020-07-06
劍指Offer_#32_從上到下列印二叉樹
劍指offerContents
這一題有三個變式,題目有細微差別.
劍指Offer32-I:不分行從上到下列印二叉樹
題目
從上到下打印出二叉樹的每個節點,同一層的節點按照從左到右的順序列印。
例如:
給定二叉樹:[3,9,20,null,null,15,7],
3 / \ 9 20 / \ 15 7
返回:
[3,9,20,15,7]
提示:
節點總數 <= 1000
思路分析
這一題的遍歷方式就是廣度優先遍歷(BFS),可以藉助佇列資料結構來實現。
演算法流程
- 特殊情況:輸入為null,直接返回空陣列。
- 初始化:初始化佇列
q
,將root
加入佇列,初始化結果列表res
。 - while迴圈:
- 迴圈條件:佇列不為空
- 迴圈內容:
- 取出隊首元素
cur
- 將
cur
的值加入到res
- 把
cur
的左右位元組點加入佇列q
- 取出隊首元素
- 返回結果:將
res
轉換為指定的int陣列型別。
解答
class Solution {
public int[] levelOrder(TreeNode root) {
if (root == null) return new int[0];
ArrayList<Integer> res= new ArrayList<>();
//注意Queue的例項化方法,右邊寫的是LinkedList,因為LinkedList實現了Queue介面
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
//取出隊首元素
TreeNode cur = q.poll();
//取出的元素,加入到res列表
res.add(cur.val);
//繼續將當前節點的左右子節點加入佇列
if(cur.left != null) q.offer(cur.left);
if(cur.right != null) q.offer(cur.right);
}
//不能使用res.toArray()作為返回值,因為這樣返回型別是Integer[],而非int[]
//只能for迴圈賦值給int[]
int[] intRes = new int[res.size()];
for(int i = 0;i <= intRes.length - 1;i++){
intRes[i] = res.get(i);
}
return intRes;
}
}
劍指Offer32-II:分行從上到下列印二叉樹
題目
從上到下按層列印二叉樹,同一層的節點按從左到右的順序列印,每一層列印到一行。
例如:
給定二叉樹:[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其層次遍歷結果:
[
[3],
[9,20],
[15,7]
]
提示:
節點總數 <= 1000
思路分析
和上一題相比,多了一個分行列印的要求。
思路是,while迴圈當中再加入一層for迴圈,每個for迴圈列印一層的內容。
關鍵在於如何控制for迴圈剛好列印完一層節點就結束?
很巧妙的思路是:迴圈變數i時候使用佇列長度來初始化,每次迴圈i遞減。
這樣正好可以把一層的節點新增完。
解答
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
List<Integer> tmp = new ArrayList<>();
//ERROR:這樣寫不行,因為q.size()每一輪都在變化,應該把q.size()作為初始化
//for(int i = 0;i <= q.size() - 1;i++){
for(int i = q.size();i > 0;i--){
TreeNode cur = q.poll();
tmp.add(cur.val);
if(cur.left != null) q.offer(cur.left);
if(cur.right != null) q.offer(cur.right);
}
res.add(tmp);
}
return res;
}
}
劍指Offer32-III:之字形從上到下列印二叉樹
題目
請實現一個函式按照之字形順序列印二叉樹,即第一行按照從左到右的順序列印,第二層按照從右到左的順序列印,第三行再按照從左到右的順序列印,其他行以此類推。
例如:
給定二叉樹:[3,9,20,null,null,15,7],
3
/ \
9 20
/ \
15 7
返回其層次遍歷結果:
[
[3],
[20,9],
[15,7]
]
提示:
節點總數 <= 1000
思路分析
跟上一題基本一樣,唯一的區別在於,需要根據層數的奇偶來控制列印順序。只需要在向tmp
新增元素的時候,加一個條件判斷即可。
解答
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()){
List<Integer> tmp = new ArrayList<>();
for(int i = q.size();i > 0;i--){
TreeNode cur = q.poll();
//相比上一題改動的地方
//當前已經打印出來的層數是偶數層,那麼目前列印的是奇數層,應該按照從左到右的順序
if(res.size() % 2 == 0) tmp.add(cur.val);
//當前已經打印出來的層數是奇數層,那麼目前列印的是偶數層,應該按照從右到左的順序
else tmp.add(0,cur.val);
if(cur.left != null) q.offer(cur.left);
if(cur.right != null) q.offer(cur.right);
}
res.add(tmp);
}
return res;
}
}