主頁 >  其他 > 代碼隨想錄 | 二叉樹

代碼隨想錄 | 二叉樹

2022-10-12 07:55:16 其他

226. 翻轉二叉樹

給你一棵二叉樹的根節點 root ,翻轉這棵二叉樹,并回傳其根節點,

輸入:root = [4,2,7,1,3,6,9]
輸出:[4,7,2,9,6,3,1]

ψ(`?′)ψ 我的思路

  • 還是用了層序遍歷的方法,在該結點左右孩子入堆疊之后,互換左右指標
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public TreeNode invertTree(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<>();
        if (root == null) {
            return root;
        }
        que.add(root);
        while (!que.isEmpty()) {
            int size = que.size();
            while (size > 0) {
                TreeNode node = que.poll();
                TreeNode tmp = new TreeNode();
                if (node.right != null && node.left != null) {
                    //左右孩子都不空,右孩子、左孩子加入佇列并交換
                    que.add(node.right);
                    que.add(node.left);
                    tmp = node.right;
                    node.right = node.left;
                    node.left = tmp;
                } else if (node.right==null&&node.left!=null ) {
                    que.add(node.left);
                    node.right=node.left;
                    node.left=null;
                } else if(node.left==null&&node.right!=null){
                    que.add(node.right);
                    node.left=node.right;
                    node.right=null;
                }
                size--;
            }
        }
        return root;
    }
}
  • 下面是遞回的做法:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
   public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        //先序遍歷
        swapChildren(root);
        invertTree(root.left);
        invertTree(root.right);
        return root;
    }

    private void swapChildren(TreeNode root) {
        TreeNode tmp = root.left;
        root.left = root.right;
        root.right = tmp;
    }
}



101. 對稱二叉樹

給你一個二叉樹的根節點 root , 檢查它是否軸對稱,

輸入:root = [1,2,2,3,4,4,3]
輸出:true

ψ(`?′)ψ 我的思路

  • 層序遍歷每一層二叉樹,每一層結點的值放入鏈表,判斷鏈表(除第一層外)是否對稱
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<>();
        que.add(root);
        while (!que.isEmpty()){
            int size = que.size();
            List<Integer> list = new ArrayList<>();
            while (size>0){
                TreeNode node = que.poll();
                list.add(node.val);//加入鏈表
                if(node.left!=null){que.add(node.left);}
                if(node.right!=null){que.add(node.right);}
                size--;
            }
            //判斷list是不是對稱串列
            if(list.size()>1){
                Collections.reverse(list.subList(0,list.size()/2));
                if(!list.subList(0,list.size()/2).equals(list.subList(list.size()/2,list.size()))){
                    return false;
                }
            }
        }
        return true;
    }
}
  • 上面的代碼并不能判斷下面這種情況:

    輸入:root = [1,2,2,null,3,null,3]
    輸出:false

  • 因為只把不空的結點加入到鏈表,所以上述情況的鏈表是這樣的:[1][2,2][3,3],我想著把null也加入到鏈表里,不行(x_x),那樣的話就沒辦法控制臨界條件了,

  • 下面是代碼隨想錄的遞回做法:比較根結點的左右子樹是否對稱

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSymmetric(TreeNode root) {
        boolean res = comparable(root.left, root.right);
        return res;

    }
    public static boolean comparable(TreeNode left, TreeNode right){
        if(left==null&&right!=null){return false;}
        else if(right==null&&left!=null){return false;}
        else if(right==null&&left==null){return true;}
        else if(right.val!= left.val){return false;}
        boolean a = comparable(left.left, right.right);//比較外側結點
        boolean b = comparable(left.right, right.left);//比較內測結點
        boolean res = a && b;
        return  res;
    }
}
  • 感覺遞回的做法要好理解很多,再寫兩道類似的題目練一下遞回


100. 相同的樹

給你兩棵二叉樹的根節點 p 和 q ,撰寫一個函式來檢驗這兩棵樹是否相同,
如果兩個樹在結構上相同,并且節點具有相同的值,則認為它們是相同的,

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
       //if(p==null&&q==null){return false;}
        return comparable(p,q);
    }

    public boolean comparable(TreeNode p,TreeNode q){
        if(p!=null&&q==null){return false;}
        else if(p==null&&q==null){return true;}
        else if(p==null&&q!=null){return false;}
        else if(p.val!=q.val){return false;}
        boolean a = comparable(p.left,q.left);
        boolean b = comparable(p.right,q.right);
        return a && b;
    }
}



572. 另一棵樹的子樹

給你兩棵二叉樹 root 和 subRoot ,檢驗 root 中是否包含和 subRoot 具有相同結構和節點值的子樹,如果存在,回傳 true ;否則,回傳 false ,
二叉樹 tree 的一棵子樹包括 tree 的某個節點和這個節點的所有后代節點,tree 也可以看做它自身的一棵子樹,

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        //前序遍歷root
        List<TreeNode> nodes = new ArrayList<>();
        preorder(root,nodes);
        for (TreeNode node : nodes) {
            //此時nodes里面是root中的所有結點
            if(comparable(node, subRoot)){
                return true;
            }
        }
        return false;
    }
    public void preorder(TreeNode root, List<TreeNode> nodes){
        if(root==null){return ;}
        nodes.add(root);
        preorder(root.left,nodes);
        preorder(root.right,nodes);
    }
    
    public boolean comparable(TreeNode left,TreeNode right){
        if(left==null&&right==null){return true;}
        else if(left!=null&&right==null){return false;}
        else if(left==null&&right!=null){return false;}
        else if(left.val!= right.val){return false;}
        boolean a = comparable(left.left, right.left);
        boolean b = comparable(left.right, right.right);
        return a && b;
    }
}



104. 二叉樹的最大深度

  • 這題昨天用層序遍歷寫過,下面是遞回的實作:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int maxDepth(TreeNode root) {
        //這里用根結點的高度表示二叉樹的最大深度
        if(root==null){return 0;}
        int leftDepth = maxDepth(root.left);//左孩子的高度
        int rightDepth = maxDepth(root.right);//右孩子的高度
        return Math.max(leftDepth,rightDepth)+1;//當前結點的高度(左孩子的高度,右孩子的高度的最大值+1)
        //后序遍歷
    }
}
  • 感覺遞回還是不太好理解


559. N 叉樹的最大深度

給定一個 N 叉樹,找到其最大深度,
最大深度是指從根節點到最遠葉子節點的最長路徑上的節點總數,
N 叉樹輸入按層序遍歷序列化表示,每組子節點由空值分隔

/*
// Definition for a Node.
class Node {
    public int val;
    public List<Node> children;

    public Node() {}

    public Node(int _val) {
        val = _val;
    }

    public Node(int _val, List<Node> _children) {
        val = _val;
        children = _children;
    }
};
*/

class Solution {
    public int maxDepth(Node root) {
        if(root==null){return 0;}
        List<Node> children = root.children;//當前結點的孩子們
        int max = 0;
        for (Node child : children) {
            int depth = maxDepth(child);
            max = Math.max(depth,max);
        }
        return max+1;
    }
}
  • 擴展成n叉樹,和二叉樹區別不大,就是孩子數不確定,用for回圈遍歷求孩子的高度就好



111. 二叉樹的最小深度

給定一個二叉樹,找出其最小深度,
最小深度是從根節點到最近葉子節點的最短路徑上的節點數量,
說明:葉子節點是指沒有子節點的節點,

ψ(`?′)ψ 我的思路

  • 稍微改了二叉樹最大深度的代碼,
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if(root==null){return 0;}//空的結點是第0層(也是遞回出口)
        int leftDepth = minDepth(root.left);
        int rightDepth = minDepth(root.right);
        return Math.min(leftDepth,rightDepth)+1;
    }
}
  • 代碼在運行下圖例子時回傳1

題目中說的是:最小深度是從根節點到最近葉子節點的最短路徑上的節點數量,

  • 在上述代碼中,只有一個孩子的結點會被誤以為是葉子結點,回傳該結點的高度,改進后代碼如下:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if(root==null){return 0;}//空的結點是第0層(也是遞回出口)
        int leftDepth = minDepth(root.left);
        int rightDepth = minDepth(root.right);
        if(root.left==null){return rightDepth+1;}//如果左子樹為空,回傳右子樹的高度+1
        else if(root.right==null){return leftDepth+1;}//如果右子樹為空,回傳左子樹的高度+1
        return Math.min(leftDepth,rightDepth)+1;
    }
}



222. 完全二叉樹的節點個數

完全二叉樹 的根節點 root ,求出該樹的節點個數,
完全二叉樹 的定義如下:在完全二叉樹中,除了最底層節點可能沒填滿外,其余每層節點數都達到最大值,并且最下面一層的節點都集中在該層最左邊的若干位置,若最底層為第 h 層,則該層包含 1~ 2h 個節點,

ψ(`?′)ψ 我的思路

  • 層序遍歷,每彈出一個數count++
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int countNodes(TreeNode root) {
        Queue<TreeNode> que = new LinkedList<>();
        if(root==null){return 0;}
        int count = 0;
        que.add(root);
        while (!que.isEmpty()){
            int size = que.size();
            while (size>0){
                count++;
                TreeNode node = que.poll();
                if(node.left!=null){que.add(node.left);}
                if(node.right!=null){que.add(node.right);}
                size--;
            }
        }
        return count;
    }
}
  • 不知道是不是昨天層序遍歷做多了,我現在拿到題想的都是層序遍歷,遞回好難想啊??
class Solution {
    // 還是展示遞回解法(后序遍歷)
    public int countNodes(TreeNode root) {
        if(root == null) {
            return 0;
        }
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}
  • 離譜離譜,就這么幾行


110. 平衡二叉樹

給定一個二叉樹,判斷它是否是高度平衡的二叉樹,
本題中,一棵高度平衡二叉樹定義為:
一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1 ,

ψ(`?′)ψ 我的思路

  • 求出根結點左右子樹的最大高度,相減取絕對值不超過1即為平衡二叉樹
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        if(root==null){return true;}
        int leftHeight = maxHeight(root.left);
        int rightHeight = maxHeight(root.right);
        if(Math.abs(leftHeight-rightHeight)<=1){
            return true;
        } else{return false;}
    }

    public int maxHeight(TreeNode root){
        if(root==null){return 0;}
        return Math.max(maxHeight(root.left),maxHeight(root.right))+1;
    }
}

  • 按我的思路,這就是個平衡二叉樹,仔細讀題后發現:

一個二叉樹每個節點 的左右兩個子樹的高度差的絕對值不超過 1 ,

  • 應該在外面再套一個回圈,但是那樣代碼就太復雜了,下面是代碼隨想錄的解法:
  • 先來區分一下高度和深度(高度用后序遍歷,深度用前序遍歷)

    上面的題目中有求二叉樹最大深度的題目,用到后序遍歷,是因為求二叉樹的最大深度就是求根結點的高度
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        //后序遍歷
        int height = getHeight(root);
        if(height==-1){return false;}
        else return true;
    }

   public int getHeight(TreeNode root){
        if(root==null){
            return 0;//null結點高度為0
        }
       int leftHeight = getHeight(root.left);//左子樹的高度
       if(leftHeight==-1){return -1;}
       int rightHeight = getHeight(root.right);//右子樹的高度
       if(rightHeight==-1){return -1;}
       if(Math.abs(leftHeight-rightHeight)>1){return -1;}//當前結點左右子樹高度差>1
       return 1+Math.max(leftHeight,rightHeight);//回傳當前結點的高度
    }
}
  • 遞回,遞回,又是你!!!


257. 二叉樹的所有路徑

給你一個二叉樹的根節點 root ,按 任意順序 ,回傳所有從根節點到葉子節點的路徑,
葉子節點 是指沒有子節點的節點,

  • 這題用到了回溯,不懂回溯,偷了張圖大概看一下
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<>();//結果串列
        if(root==null){return res;}
        List<Integer> path = new ArrayList<Integer>();//路徑串列(存放經過結點的值)
        postOrder(root,path,res);
        return res;
    }

    public void postOrder(TreeNode node,List<Integer> path,List<String> res){
        path.add(node.val);//每一個結點都加在路徑里面
        if(node.left==null&&node.right==null){//如果node沒孩子(葉子節點)
            //就可以把path轉換成String加到res中啦
            StringBuilder sb = new StringBuilder();
            for (Integer i : path) {
                sb.append(i+"->");
            }
            String s = sb.toString();
            s = s.substring(0,s.length()-2);//把最后一個->去掉
            res.add(s);
        }
       if (node.left != null) {
            postOrder(node.left, path, res);
            path.remove(path.size()-1);//回溯
        }
        if (node.right != null) {
            postOrder(node.right, path, res);
            path.remove(path.size()-1);//回溯
        }
    }
}
  • 這題挺好,標記,


404. 左葉子之和

給定二叉樹的根節點 root ,回傳所有左葉子之和,

  • 這題的突破點是找左葉子的定義:當一個結點的左孩子不空(無所謂右孩子),且左孩子沒孩子,即為左葉子,
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        if(root==null){
            return 0;
        }
        int midValue = https://www.cnblogs.com/xiannveryao/p/0;//存盤當前結點的左孩子的值
        if(root.left!=null&&root.left.left==null&&root.left.right==null){
            midValue = root.left.val;//如果root.left滿足左葉子的條件
        }
        int leftValue = sumOfLeftLeaves(root.left);
        int rightValue = sumOfLeftLeaves(root.right);
        return midValue+leftValue+rightValue;//回傳當前結點的值,加上左右孩子的葉子結點數
    }
}
  • 遞回真的是不好想啊,感覺我現在的水平只能是看懂



513. 找樹左下角的值

給定一個二叉樹的 根節點 root,請找出該二叉樹的 最底層 最左邊 節點的值,
假設二叉樹中至少有一個節點,

ψ(`?′)ψ 我的思路

  • 層序遍歷到最后一層,第一個彈出的值即為所求
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int findBottomLeftValue(TreeNode root) {
         Queue<TreeNode> que = new LinkedList<>();
        List<Integer> list = null;
        que.add(root);
        while (!que.isEmpty()){//控制層數
            list = new ArrayList<>();
            int size = que.size();
            while (size>0){//控制每層的元素個數
                TreeNode node = que.poll();
                list.add(node.val);
                if(node.left!=null){que.add(node.left);}
                if(node.right!=null){que.add(node.right);}
                if(size==1){       
                }
                size--;
            }  
        }
        return list.get(0);//因為鏈表每層都重繪,所以此時鏈表記錄的是最后一層的結點
    }
}
  • hhh,只要可以用層序遍歷,我就是小神仙??


112. 路徑總和

給你二叉樹的根節點 root 和一個表示目標和的整數 targetSum ,判斷該樹中是否存在 根節點到葉子節點 的路徑,這條路徑上所有節點值相加等于目標和 targetSum ,如果存在,回傳 true ;否則,回傳 false ,
葉子節點 是指沒有子節點的節點,

  • 感覺和上面的二叉樹的所有路徑很像,就改了一下上面的代碼,第一遍的時候是自己寫的,沒有寫出來,
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        List<Integer> res = new ArrayList<>();//用來存放所有路徑的和
        if(root==null){return false;}
        List<Integer> path = new ArrayList<Integer>();//用來存放經過結點的值
        postOrder(root,path,res);
        if(res.contains(targetSum)){return true;}
        else return false;
    }

    public void postOrder(TreeNode node,List<Integer> path,List<Integer> res){
        path.add(node.val);//每一個結點的值都加在路徑里面
        if(node.left==null&&node.right==null){//如果node沒孩子(葉子節點)
            int sum = 0;
            for (Integer i : path) {
                sum += i;
            }
            res.add(sum); //求出當前路徑的總和加到res中
        }
        if (node.left != null) {
            postOrder(node.left, path, res);
            path.remove(path.size()-1);//回溯
        }
        if (node.right != null) {
            postOrder(node.right, path, res);
            path.remove(path.size()-1);//回溯
        }
    }
}



113. 路徑總和 II

給你二叉樹的根節點 root 和一個整數目標和 targetSum ,找出所有 從根節點到葉子節點 路徑總和等于給定目標和的路徑,
葉子節點 是指沒有子節點的節點,

ψ(`?′)ψ 我的思路

  • 還是路徑的問題,我就按路徑的模板寫了一下,但是在debug的時候發現res會隨著path的改變而改變,活見鬼??,我明明已經把path加到res里了,
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
        List<List<Integer>> res = new ArrayList<>();//結果串列
        List<Integer> path = new ArrayList<>();//路徑串列
        if(root==null){return res;}
        path(root,path,res,targetSum);
        return res;
    }

    void path(TreeNode node,List<Integer> path,List<List<Integer>> res,int targetSum){
        path.add(node.val);
        if(node.left==null&&node.right==null){//到達了葉子結點
            int sum = 0;
            for (Integer i : path) {
                sum+=i;
            }
            if(sum==targetSum){res.add(path);}
        }
       if (node.left != null) {
            path(node.left, path, res, targetSum);
            path.remove(path.size()-1);//回溯
        }
        if (node.right != null) {
            path(node.right, path, res, targetSum);
            path.remove(path.size()-1);//回溯
        }
    }
}
  • 但仔細一想應該是遞回的問題,我找不到解決的方法,看了題解后發現其實就是一行代碼
 if(sum==targetSum){ res.add(new ArrayList<>(path));}
  • 活見鬼??,剛開始看的時候我就不相信這是java的語法,我就沒見過泛型后面的小括號里面放東西??,但是運行通過,網上也找不到靠譜的解釋,我猜是新建了一個與path相同型別的鏈表把path裝了進來,這樣我再debug,res就不會隨著遞回變化了,

?標記,標記,這一題不太會



106. 從中序與后序遍歷序列構造二叉樹

給定兩個整數陣列 inorder 和 postorder ,其中 inorder 是二叉樹的中序遍歷, postorder 是同一棵樹的后序遍歷,請你構造并回傳這顆 二叉樹 ,

確認過眼神,是我寫不出來的題目??

  • 思路是不難理解的,偷個圖展示一下

    步驟:
  1. 判斷后序陣列是否為空
  2. 取后序陣列的最后一個值的下標切割中序陣列,把中序陣列切割成左中序和右中序
  3. 用兩個區間的長度去切割后序陣列,得到左后序和右后序
  4. 遞回(左中序,左后序),遞回(右中序,右后序)
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    Map<Integer, Integer> map;  // 方便根據數值查找位置
    public TreeNode buildTree(int[] inorder, int[] postorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的數值對應位置
            map.put(inorder[i], i);
        }
        return findNode(inorder,  0, inorder.length, postorder,0, postorder.length);  // 前閉后開
    }
    
    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] postorder, int postBegin, int postEnd) {
        // 引數里的范圍都是前閉后開
        if (inBegin >= inEnd || postBegin >= postEnd) {  // 不滿足左閉右開,說明沒有元素,回傳空樹
            return null;
        }
        int rootIndex = map.get(postorder[postEnd - 1]);  // 找到后序遍歷的最后一個元素在中序遍歷中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 構造結點
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子樹個數,用來確定后序數列的個數
        root.left = findNode(inorder, inBegin, rootIndex, postorder, postBegin, postBegin + lenOfLeft);
        root.right = findNode(inorder, rootIndex + 1, inEnd, postorder, postBegin + lenOfLeft, postEnd - 1);
        return root;
    }
}
  • ? 標記,標記,這題不是自己寫的



105. 從前序與中序遍歷序列構造二叉樹

給定兩個整數陣列 preorder 和 inorder ,其中 preorder 是二叉樹的先序遍歷, inorder 是同一棵樹的中序遍歷,請構造二叉樹并回傳其根節點,

  • 與上一題類似,改了一下上一題的代碼
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    Map<Integer, Integer> map;  // 方便根據數值查找位置
    public TreeNode buildTree(int[] preorder, int[] inorder) {
        map = new HashMap<>();
        for (int i = 0; i < inorder.length; i++) { // 用map保存中序序列的數值對應位置
            map.put(inorder[i], i);
        }
        return findNode(inorder,  0, inorder.length, preorder,0, preorder.length);  // 前閉后開
    }
    
    public TreeNode findNode(int[] inorder, int inBegin, int inEnd, int[] preorder, int preBegin, int preEnd) {
        // 引數里的范圍都是前閉后開
        if (inBegin >= inEnd || preBegin >= preEnd) {  // 不滿足左閉右開,說明沒有元素,回傳空樹
            return null;
        }
        int rootIndex = map.get(preorder[preBegin]);  // 找到前序遍歷的最后一個元素在中序遍歷中的位置
        TreeNode root = new TreeNode(inorder[rootIndex]);  // 構造結點
        int lenOfLeft = rootIndex - inBegin;  // 保存中序左子樹個數,用來確定前序數列的個數
        root.left = findNode(inorder, inBegin, rootIndex, preorder, preBegin+1, preBegin + lenOfLeft+1);
        root.right = findNode(inorder, rootIndex + 1, inEnd, preorder, preBegin + lenOfLeft+1, preEnd);
        return root;
    }
}
  • 太殘忍了,太殘忍了,最后這兩題,就是在屠殺我的腦細胞??,不知道看多少集海綿寶寶才能養回來



總結


  • 今天的題比昨天的題要好,每一道題都很有代表性??

  • 翻轉二叉樹:交換結點指向左右孩子的指標

  • 對稱二叉樹:以根結點所在豎直線為對稱軸,先比較外側結點,后比較內側結點(相同的樹,另一棵樹的子樹類似)(有點像雙指標

  • 二叉樹的最大深度:求二叉樹的最大深度就是求根結點的高度,求高度用后序遍歷,當前結點的高度是左右孩子高度的最大值+1(N叉樹的最大深度類似)

  • 二叉樹的最小深度:如果左子樹為空,當前結點的高度為右子樹的高度+1;如果右子樹為空,當前結點的高度為左子樹的高度+1,畫個圖你就知道啦??

  • 完全二叉樹的結點個數:基礎的遍歷題

  • 平衡二叉樹:求高度的題,要用后序遍歷

  • 二叉樹的所有路徑:求路徑的題,要用到回溯,需要什么條件就往遞回方法中加引數就可

  • 左葉子之和:關鍵是判斷左葉子

  • 找樹左下角的值:層序遍歷

  • 路徑總和:改路徑題的模板(其實還是有點迷的,尤其是遞回方法帶引數,好家伙,那是一個千變萬化,根本分析不出來??)

  • 從中/前序后序遍歷序列構造二叉樹,重點在區間的劃分

  • 遇到問題總是先想層序遍歷,但是感覺遞回才是正統解法,要好好掌握遞回才行

  • 做了一天的二叉樹,現在感覺我就是個二叉樹??

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/513683.html

標籤:其他

上一篇:leet Code [209. Minimum Size Subarray Sum]

下一篇:行程和計劃任務

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more