沒有遞歸解決不了的二叉樹問題

Leetcode上的前120道題的簡單題已經(jīng)幾乎做完了,遞歸數(shù)據(jù)類型的題還是遇到不少。遞歸是一種比較優(yōu)雅的解題方法,奈何我并不能每次都很順利地寫出遞歸解法,所以在這里做一個(gè)Leetcode前120道簡單題之二叉樹問題遞歸解法總結(jié)。


100.相同的數(shù)

給定兩個(gè)二叉樹,編寫一個(gè)函數(shù)來檢驗(yàn)它們是否相同。

如果兩個(gè)樹在結(jié)構(gòu)上相同,并且節(jié)點(diǎn)具有相同的值,則認(rèn)為它們是相同的。

/**定義二叉樹類,后同,省略

* Definition for a binary tree node.

* public class TreeNode {

*    int val;

*    TreeNode left;

*    TreeNode right;

*    TreeNode(int x) { val = x; }

* }

*/

class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        //結(jié)束標(biāo)志:兩個(gè)樹均為空
        if(p == null && q == null){
            return true;
        }
        //兩樹均不為空且值相同
        if(p != null && q != null && p.val == q.val){
            return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
        }else{
            return false;
        }
    }
}


101.對(duì)稱二叉樹
給定一個(gè)二叉樹,檢查它是否是鏡像對(duì)稱的。
例如,二叉樹 [1,2,2,3,4,4,3] 是對(duì)稱的。

class Solution {
    //結(jié)束標(biāo)志:根節(jié)點(diǎn)為空,或者根節(jié)點(diǎn)的只有左子樹或右子樹
    public boolean isSymmetric(TreeNode root) {
        if(root == null){
            return true;
        }
        if((root.left == null && root.right != null)||(root.left != null && root.right == null)){
            return false;
        }
        return isSymmetricChild(root.left, root.right);
        
    }
    //對(duì)稱的情況:左右葉子節(jié)點(diǎn)均為空;左右葉子節(jié)點(diǎn)的值相同(則將子節(jié)點(diǎn)的左右子樹作為輸入再次迭代)
    private boolean isSymmetricChild(TreeNode left, TreeNode right){
        if(left == null && right == null){
            return true;
        }
        if((left == null && right != null)||(right == null && left != null)){
            return false;
        }
        if(left.val == right.val){
            return isSymmetricChild(left.left,right.right) && isSymmetricChild(right.left,left.right);
        }
        else{
            return false;
        }
    }
}


104.二叉樹的最大深度
給定一個(gè)二叉樹,找出其最大深度。
二叉樹的深度為根節(jié)點(diǎn)到最遠(yuǎn)葉子節(jié)點(diǎn)的最長路徑上的節(jié)點(diǎn)數(shù)。

class Solution {
    public int maxDepth(TreeNode root) {
        //結(jié)束標(biāo)志:根節(jié)點(diǎn)為空
        if(root == null){
            return 0;
        };
        //左右子樹的最大深度,+1
        int left = maxDepth(root.left) + 1;
        int right = maxDepth(root.right) + 1;
        int max = Math.max(left, right);
        //返回子樹最大深度的最大值
        return max;
    }
}


108.將有序數(shù)組轉(zhuǎn)化成二叉搜索樹
將一個(gè)按照升序排列的有序數(shù)組,轉(zhuǎn)換為一棵高度平衡二叉搜索樹。
本題中,一個(gè)高度平衡二叉樹是指一個(gè)二叉樹每個(gè)節(jié)點(diǎn) 的左右兩個(gè)子樹的高度差的絕對(duì)值不超過 1。
示例:

給定有序數(shù)組: [-10,-3,0,5,9],
一個(gè)可能的答案是:[0,-3,9,-10,null,5],它可以表示下面這個(gè)高度平衡二叉搜索樹:


class Solution {
    //結(jié)束標(biāo)志:待轉(zhuǎn)化的數(shù)組為空
    public TreeNode sortedArrayToBST(int[] nums) {
        return nums == null ? null : buildTree(nums, 0, nums.length - 1);
    }
    
    private TreeNode buildTree(int[] nums, int l , int r){
        if(l > r){
            return null;
        }
        //找到數(shù)組中點(diǎn)作為根節(jié)點(diǎn)
        int m = l + (r - l) / 2;
        TreeNode root = new TreeNode(nums[m]);
        //左右子樹分別建立二叉樹
        root.left = buildTree(nums, l , m - 1);
        root.right = buildTree(nums, m + 1, r);
        //返回根節(jié)點(diǎn)
        return root;
    }
}



110.平衡二叉樹
給定一個(gè)二叉樹,判斷它是否是高度平衡的二叉樹。

class Solution {
    
    public boolean isBalanced(TreeNode root) {
        return isBST(root).isB;
    }
    
    private class ReturnNode {
        boolean isB;
        int depth;
        public ReturnNode(boolean isB, int depth){
            this.isB = isB;
            this.depth = depth;
        }
    }
     
   //結(jié)束標(biāo)志:根節(jié)點(diǎn)為空 
    public ReturnNode isBST(TreeNode root) {
        if(root == null) {
            return new ReturnNode(true, 0);
        }
         
        //不平衡的三種情況:左數(shù)不平衡, 右數(shù)不平衡 ,左右樹深度差值大于1
        ReturnNode left = isBST(root.left);
        ReturnNode right = isBST(root.right);
        if(left.isB == false || right.isB == false) {
            return new ReturnNode(false, 0);
        }
        if(Math.abs(left.depth - right.depth) > 1) {
            return new ReturnNode(false, 0);
        }
        //返回左右子樹的最大深度,+1
        return new ReturnNode(true, Math.max(left.depth, right.depth) + 1);
    }
}


111.二叉樹的最小深度
給定一個(gè)二叉樹,找出其最小深度。
最小深度是從根節(jié)點(diǎn)到最近葉子節(jié)點(diǎn)的最短路徑上的節(jié)點(diǎn)數(shù)量。

class Solution {
    public int minDepth(TreeNode root) {
        //結(jié)束標(biāo)志:根節(jié)點(diǎn)為空
        if(root == null){
            return 0;
        }
        if(root.left == null && root.right == null) {
            return 1;
        }
        //左右子樹的最小深度,+1
        int a = minDepth(root.left) + 1;
        a = (a==1 ? Integer.MAX_VALUE : a);
        int b = minDepth(root.right) + 1;
        b = (b==1 ? Integer.MAX_VALUE : b);
        int min = Math.min(a, b);//
        //返回子樹中的最小深度
        return min;
    }
}


小結(jié):其實(shí)遞歸解法的代碼是有一定的規(guī)律的,主要需要注意三個(gè)地方:

  • 遞歸結(jié)束的標(biāo)志
  • 單層遞歸中需要做的事情
  • 每層遞歸給下一層傳的返回值。

更新:好久沒做,又有點(diǎn)忘了怎么寫遞歸的程序了,補(bǔ)充一道2019/10/23做的題。
226.翻轉(zhuǎn)二叉樹
翻轉(zhuǎn)一棵二叉樹。

class Solution {
    public TreeNode invertTree(TreeNode root) {
        //結(jié)束標(biāo)識(shí):節(jié)點(diǎn)為空
        if (root == null) {
            return root;
        } else {
            //交換操作
            TreeNode node = root.right;
            root.right = root.left;
            root.left = node;
            
            root.right = invertTree(root.right);
            root.left = invertTree(root.left);
        }
        return root;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容