Leetcode 二叉樹題目集合 (看完這個面試不會做二叉樹題,辣條給你!!!!!)

Remember發表於2019-06-01

✏️Leetcode經典二叉樹題目集合
開題:這位同志,麻煩你手寫一個紅黑樹出來......告辭!!!!!

✏️1.二叉樹的前序遍歷(leetcode144)

前序遍歷,先訪問根結點,然後在訪問左子樹,最後訪問右子樹。可以利用棧的特點,這裡我結合了佇列和棧的特點來實現。先壓入樹,取出根節點。先把根節點值push到佇列中,然後把右子樹壓入棧中,最後壓入左子樹。返回佇列。當然你可以調整成你想要的實現方式。(只要前中後序順序理解正確即可)

/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     public $val = null;
 *     public $left = null;
 *     public $right = null;
 *     function __construct($value) { $this->val = $value; }
 * }
 */

class Solution {

    /**
     * @param TreeNode $root
     * [@return](https://learnku.com/users/31554) Integer[]
     */
    function preorderTraversal($root) {
        $res=[];
        $list=[];
        array_unshift($res,$root);
        while(!empty($res)){
           $current=array_shift($res);
           if($current==null) continue;
            array_push($list,$current->val);
            array_unshift($res,$current->right);
            array_unshift($res,$current->left);           
        }
        return $list; 
    }
}

✏️2.二叉樹的中序遍歷(leetcode94)

  /**
     * @param TreeNode $root
     * @return Integer[]
     */
    function inorderTraversal($root) {
        $res=[];
        $this->helper($root,$res);
        return $res;
    }
    function helper($root,&$res){
        if($root !=null){
            if($root->left !=null) $this->helper($root->left,$res);
            array_push($res,$root->val);
            if($root->right !=null)  $this->helper($root->right,$res);
        }

    }

或者不用遞迴

    /**
     * @param TreeNode $root
     * @return Integer[]
     */
    function inorderTraversal($root) {
        $res=[];
        $list=[];
        while(!empty($list) ||  $root !=null){
            while($root != null){
                array_unshift($list,$root);
                $root=$root->left;
            }
            $root=array_shift($list);
            array_push($res,$root->val);
            $root=$root->right;
        }
        return $res;
    }

✏️3.二叉樹的後序遍歷(leetcode145)

    /**
     * @param TreeNode $root
     * @return Integer[]
     */
    function postorderTraversal($root) {
       $list=[];
        $res=[];
        array_push($list,$root);
        while(!empty($list)){
            $node=array_shift($list);
            if(!$node) continue;
            array_unshift($res,$node->val);
            array_unshift($list,$node->left);
            array_unshift($list,$node->right);
        }
        return $res;
    }
}

✏️4.二叉樹的層次遍歷(leetcode102)

DFS和BFS都可以解,竟然已經要我們按照層列印了,那麼先使用BFS,思路就是先判斷樹是否是空,不是空加入一個佇列的結構中,如果佇列不為空,取出頭元素,那麼當前元素表示的就是當前這一層了,所以只需要遍歷這一層裡的所有的元素即可,然後下一層....


 class Solution {

    /**
     * @param TreeNode $root
     * @return Integer[][]
     */
    function levelOrder($root) {
        if(empty($root)) return [];
        $result = [];
        $queue = [];
        array_push($queue,$root);
        while(!empty($queue)){
            $count = count($queue);
            $leveQueue = [];
            for($i = 0;$i<$count;$i++){
                $node = array_shift($queue);
                array_push($leveQueue,$node->val);
                if($node->left) array_push($queue,$node->left);
                if($node->right) array_push($queue,$node->right);
            }
            array_push($result,$leveQueue);
        }
        return $result;
    }
}

如果使用DFS的話,就是一條路走到黑,然後再重新一路路的退回來再找下一路,所以這樣的話,每一次我們需要記錄一下當前他所在的這個點屬於哪一層即可,程式碼用遞迴實現。

class Solution {

    /**
     * @param TreeNode $root
     * @return Integer[][]
     */
    function levelOrder($root) {
        if(empty($root)) return [];
        $result=[];
        $this->helper($result,$root,0);
        return $result;
    }

    function helper(&$result,$node,$level){
        if(empty($node)) return ;
        if(count($result)<$level+1){
            array_push($result,[]); //說明當前行沒有結果
        }
        array_push($result[$level],$node->val);
        $this->helper($result,$node->left,$level+1);
        $this->helper($result,$node->right,$level+1);
    }
}

✏️5.二叉樹的最大深度(leetcode104)

DFS和BFS都可以解,竟然已經要我們按照層列印了,那麼先使用BFS,思路就是先判斷樹是否是空,不是空加入一個佇列的結構中,如果佇列不為空,取出頭元素,那麼當前元素表示的就是當前這一層了,所以只需要遍歷這一層裡的所有的元素即可,然後下一層....

/**
     * @param TreeNode $root
     * @return Integer
     */
    function maxDepth($root) {
        if(empty($root)) return 0;
        $left = $this->maxDepth($root->left);
        $right = $this->maxDepth($root->right);
        return $left<$right?  $right+1:$left+1;
        return max($left,$right)+1;
    }

✏️6.二叉樹的最小深度(leetcode111)

DFS和BFS都可以求解

//BFS
 /**
     * @param TreeNode $root
     * @return Integer
     */
    function minDepth($root) {
       if(empty($root)) return 0;
        if(!$root->right) return $this->minDepth($root->left)+1;
        if(!$root->left) return $this->minDepth($root->right)+1;
        $left=$this->minDepth($root->left);
        $right=$this->minDepth($root->right);
        return min($left,$right)+1;     
    }

//DFS
 /**
     * @param TreeNode $root
     * @return Integer
     */
    function minDepth($root) {
        if(empty($root)) return 0;
           $left=$this->minDepth($root->left);
          $right=$this->minDepth($root->right);
        if($left==0 || $right==0) return $left+$right+1;
        return min($left,$right)+1;
    }

✏️7.判斷是否是平衡二叉樹(leetcode110)

每一節點的兩個子樹的深度相差不能超過1。如果是空樹,直接true。

class Solution {

    /**
     * @param TreeNode $root
     * @return Boolean
     */
    private $result=true;
    function isBalanced($root) {
        if(empty($root)) return true;
        $this->helper($root);
        return $this->result;
    }
    function helper($root)
{
        if(!$root) return ;
        $left=$this->helper($root->left);
        $right=$this->helper($root->right);
        if(abs($left-$right)>1) $this->result=false;
        return max($left,$right)+1;
    }
}

✏️8.判斷是否是對稱二叉樹(leetcode101)

1.兩個子節點都是空,那說明他們是對稱的返回true

2.一個子節點為空,另一個子節點不為空,false

3.兩個子節點都不為空,但是他們不相等,false

4.兩個子節點不為空且相等,繼續判斷他們的左子樹和右子樹,把左子樹的左子節點和右子樹的右子節點進行比較,把左子樹的右子節點和右子樹的左子節點進行比較

/**
     * @param TreeNode $root
     * @return Boolean
     */
    function isSymmetric($root) {
      if(empty($root)) return true;
        return $this->helper($root->left,$root->right);
    }
    function helper($l,$r){
       if(!$l && !$r) return true;
        if(!$l || !$r || $l->val != $r->val) return false;
        return $this->helper($l->left ,$r->right) && $this->helper($l->right,$r->left);
    }

✏️9.反轉二叉樹(leetcode226)

/**
     * @param TreeNode $root
     * @return TreeNode
     */
    function invertTree($root) {
        if(!$root) return null;
        $list=[];
        array_push($list,$root);
        while(!empty($list)){
            $node=array_shift($list);
            $temp=$node->left;
            $node->left=$node->right;
            $node->right=$temp;
            if($node->left) array_push($list,$node->left);
            if($node->right) array_push($list,$node->right);
        }
        return $root;
    }

遞迴解

 /**
     * @param TreeNode $root
     * @return TreeNode
     */
    function invertTree($root) {
      if(empty($root)){
          return null;
      }
        $right=$this->invertTree($root->right);
        $left=$this->invertTree($root->left);
        $root->left=$right;
        $root->right=$left;
        return $root;
    }

✏️10.給定單連結串列(值有序)轉化成平衡二叉查詢樹(leetcode109)

先將連結串列資料轉換成有序陣列,然後利用二分查詢的特性,構建左右子樹。

/**
 * Definition for a singly-linked list.
 * class ListNode {
 *     public $val = 0;
 *     public $next = null;
 *     function __construct($val) { $this->val = $val; }
 * }
 */
/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     public $val = null;
 *     public $left = null;
 *     public $right = null;
 *     function __construct($value) { $this->val = $value; }
 * }
 */
class Solution {

    /**
     * @param ListNode $head
     * @return TreeNode
     */
    function sortedListToBST($head) {
        $data=[];
        while($head){
            array_push($data,$head->val);
            $head=$head->next;
        }
        return $this->helper($data);
    }

    function helper($data)
{
        if(!$data) return ;
        $middle=floor(count($data)/2);
        $node=new TreeNode($data[$middle]);
        $node->left=$this->helper(array_slice($data,0,$middle));
        $node->right=$this->helper(array_slice($data,$middle+1));
        return $node;
    }
}

✏️11.強盜打劫版本3(leetcode337)

最後的目的算出最多能搶金額數而不觸發報警器。除了根節點,每一個結點只有一個父節點,能直接相連的兩個節點不能同時搶,比如圖1,搶了根節點,直接相連的左右子結點就不能搶。所以要麼搶根節點的左右子結點,要麼根結點+根結點->left->right+根結點->right->right。

//遞迴  
/**
     * @param TreeNode $root
     * @return Integer
     */
    function rob($root) {
        if($root==null){
            return 0;
        }
        $res1=$root->val;
        if($root->left !=null) {
            $res1 +=$this->rob($root->left->left)+$this->rob($root->left->right);
        }
        if($root->right !=null){
            $res1 +=$this->rob($root->right->left)+$this->rob($root->right->right);
        }

        $res2=$this->rob($root->left)+$this->rob($root->right);
        return max($res1,$res2);

    }

上面那種大量的重複計算,改進一下。

如果結點不存在直接返回0,對左右結點分別遞迴,設定了4個變數,ll和lr分別表示左子結點的左右子結點的最大金額數,rl和rr分別表示右子結點的左右子結點的最大金額數。所以我們最後比較的還是兩種情況,第一種就是當前結點+左右子結點的左右子結點的值(即這裡定義的ll,lr,rl,rr).第二種是當前結點的左右子結點的值(也就是說我只搶當前結點的子結點,不搶當前結點和孫子結點),再通俗的說就是如果樹的層數是3層,要麼搶中間一層,要麼搶上下兩層,誰錢多搶誰。


/**
     * @param TreeNode $root
     * @return Integer
     */
    function rob($root) {
       $l=0;$r=0;
        return $this->countMax($root,$l,$r);
    }
    function countMax($root,&$l,&$r){
        if($root==null) return 0;
        $ll=0;$lr=0;$rl=0;$rr=0;
        $l=$this->countMax($root->left,$ll,$lr);
        $r=$this->countMax($root->right,$rl,$rr);
        return max($root->val+$ll+$lr+$rl+$rr,$l+$r);
    }

✏️12.判斷二叉樹路徑和是否存在(leetcode112)

只要使用深度優先演算法思想遍歷每一條完整的路徑,如果是個空樹直接false,如果結點沒有左右子樹(說明此時已然是葉子結點,判斷值是否是給定值,這個條件正好是遞迴終止的條件),相等直接返回true,根據這個推匯出遞迴公式。

 /**
     * @param TreeNode $root
     * @param Integer $sum
     * @return Boolean
     */
    function hasPathSum($root, $sum) {
        if($root==null){
            return false;
        }
        if($root->left ==null && $root->right==null && $root->val==$sum) return true;
        return $this->hasPathSum($root->left,$sum-$root->val) || $this->hasPathSum($root->right,$sum-$root->val);
    }

改成迭代

/**
     * @param TreeNode $root
     * @param Integer $sum
     * @return Boolean
     */
    function hasPathSum($root, $sum) {
        if($root==null){
            return false;
        }
        $res=[];
        array_push($res,$root);
        while(!empty($res)){
            $node=array_shift($res);
            if(!$node->left && !$node->right ){
                if($node->val==$sum) return true;
            }
            if($node->left){
                $node->left->val +=$node->val;
                array_push($res,$node->left);
            }
            if($node->right){
                $node->right->val +=$node->val;
                array_push($res,$node->right);
            }
        }
        return false; 
    }

✏️13.判斷是否是二叉查詢樹(leetcode98)

思路有兩種,二叉查詢樹的特點就是左子樹上的結點都小於根結點,右子樹上的結點都大於根節點。所以有兩個方向,可以分別遞迴的判斷左子樹,右子樹。或者拿左子樹上的最大值,右子樹上的最小值分別對應根結點進行判斷。


/**
 * Definition for a binary tree node.
 * class TreeNode {
 *     public $val = null;
 *     public $left = null;
 *     public $right = null;
 *     function __construct($value) { $this->val = $value; }
 * }
 */
class Solution {

    /**
     * @param TreeNode $root
     * @return Boolean
     */
    function isValidBST($root) {
       return $this->helper($root,null,null);
    }
    function helper($root,$lower,$upper){
        if($root==null) return true;
        $res=$root->val;
        if($lower !==null && $res<=$lower) return false;
        if($upper !==null && $res>=$upper) return false;
        if(!$this->helper($root->left,$lower,$res)) return false;
        if(!$this->helper($root->right,$res,$upper)) return false;
        return true;
    }
}

✏️14.找出二叉樹最後一層最左邊的值(leetcode513)

思路有兩種,二叉查詢樹的特點就是左子樹上的結點都小於根結點,右子樹上的結點都大於根節點。所以有兩個方向,可以分別遞迴的判斷左子樹,右子樹。或者拿左子樹上的最大值,右子樹上的最小值分別對應根結點進行判斷。

 /**
     * @param TreeNode $root
     * @return Integer
     */
    function findBottomLeftValue($root) {
       $data=[];
        array_push($data,$root);
        while(!empty($data)){
            $node = array_shift($data);
            if($node->right) array_push($data,$node->right);
            if($node->left) array_push($data,$node->left);
        }
        return $node->val;
    }

Github整理地址:https://github.com/wuqinqiang/leetcode-php 如果對你有幫助歡迎star

本作品採用《CC 協議》,轉載必須註明作者和本文連結
吳親庫裡

相關文章