【算法】二叉樹的層次遍歷及其衍生問題(5)


(一)二叉樹的層次遍歷

  二叉樹的層序遍歷(也叫廣度優先遍歷)的要求是:按二叉樹的層序次序(即從根結點層至葉結點層),同一層中按先左子樹再右子樹的次序遍歷二叉樹。

  層次遍歷的特點是,在所有未被訪問結點的集合中,排列在已訪問結點集合中最前面結點的左子樹的根結點將最先被訪問,然后是該結點的右子樹的根結點。這樣,如果把已訪問的結點放在一個隊列中,那么,所有未被訪問結點的訪問次序就可以由存放在隊列中的已訪問結點的出隊列次序決定。因此可以借助隊列實現二叉樹的層序遍歷

  層次遍歷算法如下:

  (1)初始化設置一個隊列;

  (2)把根結點指針入隊列;

  (3)當隊列非空時,循環執行步驟(3.a-3.c);

     (3.a)出隊列取得一個結點指針,訪問該結點;

     (3.b)若該結點的左子樹非空,則將該結點的左子樹指針入隊列;

     (3.c)若該結點的右子樹非空,則將該結點的右子樹指針入隊列;

  (4)結束。

(二)從上往下打印二叉樹

  參考:【劍指Offer】22、從上往下打印二叉樹

public class Solution {
    public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
        /*二叉樹的層次遍歷,使用隊列實現*/
        ArrayList<Integer> res=new ArrayList<>();
        if(root==null)
            return res;
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            TreeNode temp=queue.poll();
            res.add(temp.val);
            if(temp.left!=null)
                queue.add(temp.left);
            if(temp.right!=null)
                queue.add(temp.right);
        }
        return res;
    }
}

(三)把二叉樹打印成多行

  參考:【劍指Offer】60、把二叉樹打印成多行

public class Solution {
    ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        /*層次遍歷:隊列實現*/
        ArrayList<ArrayList<Integer>> res = new ArrayList<>();
        if(pRoot==null)
            return res;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(pRoot);
        while(!queue.isEmpty()){
            ArrayList<Integer> temp=new ArrayList<>();
            int len=queue.size(); //當前隊列中的節點個數,也就是當前層的節點個數
            for(int i=0;i<len;i++){ //依次取出這len個節點
                TreeNode cur=queue.poll();
                temp.add(cur.val);
                if(cur.left!=null)
                    queue.add(cur.left);
                if(cur.right!=null)
                    queue.add(cur.right);
            }
            res.add(temp);
        }
        return res;
    }
}

(四)二叉樹的左右視圖

  二叉樹的左右視圖就是從左邊(或者右邊)看二叉樹能夠看到的序列,所以其實就是每一層的第一個節點或者最后一個結點,本質上仍然是層序遍歷。

  參考LeetCode第199題:199. Binary Tree Right Side View(題目難度:medium)

class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> res=new ArrayList<>();
        if(root==null)
            return res;
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            int len = queue.size(); //當前隊列長度,也就是當前層的節點個數
            for(int i=0;i<len;i++){
                TreeNode temp=queue.poll();
                if(i==len-1)       //每一行最后一個
                    res.add(temp.val);
                if(temp.left!=null)
                    queue.add(temp.left);
                if(temp.right!=null)
                    queue.add(temp.right);
            }
        }
        return res;
    }
}

(五)之字形打印二叉樹

  參考:【劍指Offer】59、按之字形順序打印二叉樹

public class Solution {
    public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
        /*
        思路:之字形打印,用兩個棧來實現
        打印奇數行時,將他的左右節點保存到另一個棧中,先左后右
        打印偶數行時,同樣將左右節點保存到棧中,先右后左
        */
        ArrayList<ArrayList<Integer>> res=new ArrayList<>();
        if(pRoot==null)
            return res;
        Stack[] stack=new Stack[2];
        stack[0]=new Stack();
        stack[1]=new Stack();
        int num=1;
        stack[1].push(pRoot);
        while(!stack[0].isEmpty() || !stack[1].isEmpty()){
            int cur=num%2;
            ArrayList<Integer> row=new ArrayList<>();
            while(!stack[cur].isEmpty()){
                TreeNode temp=(TreeNode)stack[cur].pop();
                row.add(temp.val);
                if(cur==1){ //奇數行,先左再右
                    if(temp.left!=null)
                        stack[0].push(temp.left);
                    if(temp.right!=null)
                        stack[0].push(temp.right);
                }else{ //偶數行,先右后左
                    if(temp.right!=null)
                        stack[1].push(temp.right);
                    if(temp.left!=null)
                        stack[1].push(temp.left);
                }
            }
            res.add(row);
            num++;
        }
        return res;
    }
}

(六) 二叉樹的層平均值

題目(Easy):二叉樹的層平均值

題目描述:

給定一個非空二叉樹, 返回一個由每層節點平均值組成的數組.

示例 1:

輸入:
    3
   / \
  9  20
    /  \
   15   7
輸出: [3, 14.5, 11]
解釋:
第0層的平均值是 3,  第1層是 14.5, 第2層是 11. 因此返回 [3, 14.5, 11].

解題思路:

  本題是二叉樹層次遍歷的變種。注意防止求和時的溢出。

class Solution {
    public List<Double> averageOfLevels(TreeNode root) {
        List<Double> res=new ArrayList<>();
        if(root==null)
            return res;
        
        Queue<TreeNode> queue=new LinkedList<>();
        queue.add(root);
        while(!queue.isEmpty()){
            int num=queue.size();
            long sum=0;   //注意防止溢出
            for(int i=0;i<num;i++){
                TreeNode temp=queue.poll();
                sum+=temp.val;
                if(temp.left!=null)
                    queue.add(temp.left);
                if(temp.right!=null)
                    queue.add(temp.right);
            }
            res.add(sum*1.0/num);
        }
        return res;
    }
}

涉及題目:

leetCode102、Binary Tree Level Order Traversal

leetCode103、 Binary Tree Zigzag Level Order Traversal

leetCode107、Binary Tree Level Order Traversal II


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM