[LeetCode]-バイナリツリー-3

序文

LeetCode の質問ブラッシングで遭遇したバイナリ ツリー関連の質問を記録します (パート 3)

1302. 層内の最も深いリーフ ノードの合計

最深層の maxDepth を維持しながらバイナリ ツリーをトラバースし、res を使用して最深層のノードの数値合計を維持します。

class Solution {
    
    
    int maxDepth;
    int res;
    public void rec(TreeNode t,int depth){
    
    
        if(t == null) return;
        //遍历到比 maxDepth 更大的层数就更新maxDepth同时重置res
        if(depth > maxDepth){
    
     
            res = t.val;
            maxDepth = depth;
        }
        else if(depth == maxDepth) res += t.val;
        rec(t.left,depth + 1);
        rec(t.right,depth + 1);
    }
    public int deepestLeavesSum(TreeNode root) {
    
    
        maxDepth = -1;
        rec(root,0);
        return res;
    }
}

404.左葉の和

public int sumOfLeftLeaves(TreeNode root) {
    
    
    if(root == null) return 0;
    //如何判断左叶子,从左叶子自身并不能知道它是左叶子,
    //只能从父亲节点才能判断
    if(root.left != null && root.left.left == null && root.left.right == null){
    
    
        return root.left.val + sumOfLeftLeaves(root.right);
    }
    return sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right);
}

114. バイナリ ツリーをリンク リストに展開します

事前順序トラバーサルに基づいて、以前にトラバースしたノードも同時に維持され、現在のノードをトラバースする場合、前のノードの右側が現在のノードを指します。同時に、現在のノードの左側を null に設定する必要があり、左側のサブツリーがトラバースされると、現在のノードの右側が変更されるため、現在のノードの左右の子が最初に記録される必要があります。

class Solution {
    
    
    TreeNode prv; //记录先序遍历时上一个访问的数
    public void flatten(TreeNode root) {
    
    
        if(root == null) return;
        if(prv != null) prv.right = root;
        prv = root;
        TreeNode l =  root.left;
        TreeNode r =  root.right;
        root.left = null;
        flatten(l);
        flatten(r);
    }
}

109. 順序付きリンクリストから二分探索木への変換

順序付きリンク リストの番号シーケンスは、実際には、変換された二分探索ツリーの順序トラバーサル シーケンスであるため、順序トラバーサルに基づいてツリーを構築できます。その過程で、上のノードの値は、リンク リストはノードに順番に割り当てられます。

ツリー構築の終点は、リンクリストの長さに応じて判断する必要があります。

class Solution {
    
    
    ListNode list;
    public TreeNode sortedListToBST(ListNode head) {
    
    
        list = head;
        int length = getLength(head);
        return buildTree(0, length - 1);
    }
    public TreeNode buildTree(int left, int right) {
    
    
	    //当 left > right 其实就相当于遍历到了空结点,返回 null
        if (left > right) {
    
     
            return null;
        }
        //当[left,right]中只有偶数个数时,(left + right) >> 1 会取到两个中位数中偏小的那个数
        //但应该取偏大的那个数,所以要 (left + right + 1) >> 1
        //而当有奇数个数时,(left + right) >> 1 跟 (left + right + 1) >> 1是等价的
        int mid = (left + right + 1) >> 1;
        TreeNode root = new TreeNode();
        root.left = buildTree(left, mid - 1);
        root.val = list.val;
        list = list.next;
        root.right = buildTree(mid + 1, right);
        return root;
    }
    //计算原有序链表的长度
    public int getLength(ListNode head) {
    
    
        int count = 0;
        while (head != null) {
    
    
            count++;
            head = head.next;
        }
        return count;
    }
}

199.二分木の右側面図

階層横断に基づいて、各層が最後の要素に到達すると、その値が res に追加されます。

class Solution {
    
    
    private ArrayList<Integer> res = new ArrayList<>();
    public List<Integer> rightSideView(TreeNode root) {
    
    
        if(root != null){
    
    
            TreeNode t = root;
            LinkedList<TreeNode> queue = new LinkedList<>();
            LinkedList<TreeNode> queue1 = new LinkedList<>();
            queue.offer(t);
            while(!queue.isEmpty()){
    
    
                ArrayList<Integer> list = new ArrayList<>();
                while(!queue.isEmpty()){
    
    
                    t = queue.poll();
                    //当弹出t后栈为空,说明t是当前这一层的最后一个元素,也就是题目要的右视图在这一层的元素,所以把他的值加入res
                    if(queue.isEmpty()) res.add(t.val);
                    if(t.left != null) queue1.offer(t.left);
                    if(t.right != null) queue1.offer(t.right);
                }
                while(!queue1.isEmpty()){
    
    
                    queue.offer(queue1.poll());
                }
            }
        }
        return res;
    }
}

2 番目のブラシでは、次のバージョンのコードを作成しました。

public List<Integer> rightSideView(TreeNode root) {
    
    
    List<Integer> res = new ArrayList<>();
    if(root != null){
    
    
        TreeNode t = root;
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(t);
        while(!queue.isEmpty()){
    
    
            int size = queue.size();
            for(int i = 0;i < size;i++){
    
    
                t = queue.poll();
                if(t.left != null) queue.offer(t.left);
                if(t.right != null) queue.offer(t.right);
            }
            res.add(t.val);
        }
    }
    return res;
}

コードの最初のバージョンとの違いは、最初のバージョンでは、この走査で新しく追加されたノードの次の層を走査せずにキューを走査するために、この走査で走査されたノードの情報を保存するために 2 番目のキューが使用されることです。子ノード、このトラバーサルの終了後にそれらの子ノードを元のキューに追加します。

2 番目のバージョンでは、トラバースする前にキュー内の要素の数だけをカウントします。これらの要素が今回トラバースするノードです。その数に従ってトラバースすれば、新しく追加されたノードをトラバースすることを恐れることはありません。

637. 二分木のレベル平均

class Solution {
    
    
    private ArrayList<Double> res = new ArrayList<>();
    public List<Double> averageOfLevels(TreeNode root) {
    
    
        if(root != null){
    
    
            TreeNode t = root;
            LinkedList<TreeNode> queue = new LinkedList<>();
            LinkedList<TreeNode> queue1 = new LinkedList<>();
            queue.offer(t);
            while(!queue.isEmpty()){
    
    
            	//tem记录每层所有节点值之和
                Double tem = 0D;
                //count记录每层结点个数
                int count = 0;
                while(!queue.isEmpty()){
    
    
                    t = queue.poll();
                    tem += t.val;
                    count++;
                    if(t.left != null) queue1.offer(t.left);
                    if(t.right != null) queue1.offer(t.right);
                }
                //每遍历完一层计算一个平均值加入res
                res.add(tem / count);
                while(!queue1.isEmpty()){
    
    
                    queue.offer(queue1.poll());
                }
            }
        }
        return res;
    }
}

515. ツリーの各行の最大値を見つける

class Solution {
    
    
    ArrayList<Integer> res = new ArrayList<>();
    public List<Integer> largestValues(TreeNode root) {
    
    
        if(root != null){
    
    
            TreeNode t = root;
            LinkedList<TreeNode> queue = new LinkedList<>();
            queue.offer(t);
            while(!queue.isEmpty()){
    
    
            	//初始化最大值为最小值
                int max = Integer.MIN_VALUE;
                int count = queue.size();
                for(int i = 1;i <= count;i++){
    
    
                    t = queue.poll();
                    //如果当前节点的值大于记录的最大值那么它的值就是新的最大值
                    max = t.val > max ? t.val : max;
                    if(t.left != null) queue.offer(t.left);
                    if(t.right != null) queue.offer(t.right);
                }
                res.add(max);
            }
        }
        return res;
    }
}

116. 各ノードの右隣のノードを記入します

class Solution {
    
    
    private ArrayList<Integer> res = new ArrayList<>();
    public Node connect(Node root) {
    
    
        if(root != null){
    
    
            Node t = root;
            Node tem = null;
            LinkedList<Node> queue = new LinkedList<>();
            queue.offer(t);
            while(!queue.isEmpty()){
    
    
                int count = queue.size();
                //先让t指向当前层次第一个结点,然后从第二个结点开始遍历,tem指向新遍历到的结点,让t的next指向tem,然后再往后移动t跟tem,相当于t为前一个结点,tem为当前结点,才可以连接起来
                t = queue.poll();
                if(t.left != null) queue.offer(t.left);
                if(t.right != null) queue.offer(t.right);
                for(int i = 2;i <= count;i++){
    
    
                    tem = queue.poll();
                    t.next = tem;
                    t = tem;
                    if(tem.left != null) queue.offer(tem.left);
                    if(tem.right != null) queue.offer(tem.right);
                }
                //从循环可以看出来遍历完最后一个结点时它的next还没设定,应该设为null
                t.next = null;
            }
        }
        return root;
    }
}

117 の質問、同じアイデア、同じコード

おすすめ

転載: blog.csdn.net/Pacifica_/article/details/124509375