1. 程式人生 > 實用技巧 >劍指Offer_#32_從上到下列印二叉樹

劍指Offer_#32_從上到下列印二叉樹

劍指Offer_#32_從上到下列印二叉樹

劍指offer

Contents

這一題有三個變式,題目有細微差別.

劍指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;
    }
}