生活随笔
收集整理的這篇文章主要介紹了
leetcode: 树
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄 01二叉樹的鏡像 02 對稱的二叉樹 03 從上到下打印二叉樹 II 04二叉樹的深度 05 判斷是否是平衡二叉樹 06 重建二叉樹 07 二叉樹的最近公共祖先 08 二叉搜索樹的第k大節點 10 從上到下打印二叉樹 11二叉搜索樹與雙向鏈表 12 序列化二叉樹 13從上到下層序打印二叉樹 14 二叉搜索樹的后序遍歷序列 15 二叉樹中和為某一值的路徑 16數據流中的中位數
01二叉樹的鏡像
請完成一個函數,輸入一個二叉樹,該函數輸出它的鏡像。
來源:力扣(LeetCode) 鏈接:https://leetcode-cn.com/problems/er-cha-shu-de-jing-xiang-lcof 著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。 解題思路 方法一:利用遞歸的思想,不斷交換左右子樹,從下往上,可能會很占內存。 方法二:利用輔助棧,從上到下交換子樹,從樹根開始把樹根放到棧里,然后彈出棧頂元素,將棧頂元素的子樹交換位置,同時將非空子樹繼續放到棧里。循環操作,直到棧空。避免了遞歸調用,對內存使用不大。
class Solution {
public :
TreeNode
* mirrorTree ( TreeNode
* root
) { if ( root
== NULL ) { return NULL ; } stack
< TreeNode
* > NodeStack
; NodeStack
. push ( root
) ; while ( ! NodeStack
. empty ( ) ) { TreeNode
* temp
= NodeStack
. top ( ) ; NodeStack
. pop ( ) ; if ( temp
-> right
!= NULL || temp
-> left
!= NULL ) { TreeNode
* temp2
= temp
-> left
; temp
-> left
= temp
-> right
; temp
-> right
= temp2
; if ( temp
-> left
!= NULL ) { NodeStack
. push ( temp
-> left
) ; } if ( temp
-> right
!= NULL ) { NodeStack
. push ( temp
-> right
) ; } } } return root
; }
} ;
02 對稱的二叉樹
請實現一個函數,用來判斷一棵二叉樹是不是對稱的。如果一棵二叉樹和它的鏡像一樣,那么它是對稱的。 解題思路 方法一:建立兩個輔助棧,一個存儲根節點左子樹的內容,按照先左后右的順序存儲;一個存儲根節點右子樹內容,按照先右后左的順序。 方法2:建立兩個棧 一個棧來存儲前序遍歷左子樹優先的所有數據,一個用來存儲前序遍歷右子樹優先的所有數據,然后對兩個棧內的數據一一比較。 方法三利用遞歸的方法成對判斷節點,然后繼續判斷L.left 和 R.right,以及L.right 和R.left
class Solution {
public :
bool equal ( TreeNode
* left
, TreeNode
* right
) { if ( left
== NULL & right
== NULL ) return true ; if ( left
== NULL || right
== NULL ) return false ; if ( left
-> val
!= right
-> val
) return false ; if ( ! equal ( left
-> left
, right
-> right
) ) return false ; if ( ! equal ( left
-> right
, right
-> left
) ) return false ; return true ; } bool isSymmetric ( TreeNode
* root
) { if ( root
== NULL ) return true ; if ( root
-> left
== NULL & root
-> right
== NULL ) return true ; bool TF
= equal ( root
-> left
, root
-> right
) ; return TF
; }
} ;
03 從上到下打印二叉樹 II
從上到下按層打印二叉樹,同一層的節點按從左到右的順序打印,每一層打印到一行。
class Solution {
public :
vector
< vector
< int >> levelOrder ( TreeNode
* root
) { vector
< vector
< int >> printTree
; if ( root
== NULL ) return printTree
; stack
< TreeNode
* > firstStack
; stack
< TreeNode
* > secondStack
; firstStack
. push ( root
) ; while ( ! ( firstStack
. empty ( ) && secondStack
. empty ( ) ) ) { if ( ! firstStack
. empty ( ) ) { vector
< int > printLevelFirst
; while ( ! firstStack
. empty ( ) ) { TreeNode
* topNode
= firstStack
. top ( ) ; firstStack
. pop ( ) ; printLevelFirst
. push_back ( topNode
-> val
) ; if ( topNode
-> left
!= NULL ) { secondStack
. push ( topNode
-> left
) ; } if ( topNode
-> right
!= NULL ) { secondStack
. push ( topNode
-> right
) ; } } secondStack
= traverseStack ( secondStack
) ; printTree
. push_back ( printLevelFirst
) ; } if ( ! secondStack
. empty ( ) ) { vector
< int > printLevelSecond
; while ( ! secondStack
. empty ( ) ) { TreeNode
* topNode
= secondStack
. top ( ) ; secondStack
. pop ( ) ; printLevelSecond
. push_back ( topNode
-> val
) ; if ( topNode
-> left
!= NULL ) { firstStack
. push ( topNode
-> left
) ; } if ( topNode
-> right
!= NULL ) { firstStack
. push ( topNode
-> right
) ; } } firstStack
= traverseStack ( firstStack
) ; printTree
. push_back ( printLevelSecond
) ; } } return printTree
; } stack
< TreeNode
* > traverseStack ( stack
< TreeNode
* > stackIn
) { stack
< TreeNode
* > stackOut
; while ( ! stackIn
. empty ( ) ) { TreeNode
* topNode
= stackIn
. top ( ) ; stackOut
. push ( topNode
) ; stackIn
. pop ( ) ; } return stackOut
; }
} ;
04二叉樹的深度
代碼
class Solution {
public :
int maxDepth ( TreeNode
* root
) { return getTreeNodeHeight ( root
) ; } int getTreeNodeHeight ( TreeNode
* root
) { if ( root
== NULL ) { return 0 ; } if ( ( root
-> left
== NULL ) & ( root
-> right
== NULL ) ) { return 1 ; } else { int a
= getTreeNodeHeight ( root
-> left
) ; int b
= getTreeNodeHeight ( root
-> right
) ; if ( a
> b
) { return a
+ 1 ; } else { return b
+ 1 ; } } return 0 ; } ;
} ;
05 判斷是否是平衡二叉樹
解題思想 //方法一:利用遞歸思想,分別判斷子節點是否是平衡樹
class Solution {
public :
bool isBalanced ( TreeNode
* root
) { if ( root
== NULL ) { return true ; } if ( nodeIsBalance ( root
) ) { return ( isBalanced ( root
-> left
) & isBalanced ( root
-> right
) ) ; } return false ; } int getNodeHeight ( TreeNode
* root
) { if ( root
== NULL ) { return 0 ; } if ( ( root
-> left
== NULL ) & ( root
-> right
== NULL ) ) { return 1 ; } else { int a
= getNodeHeight ( root
-> left
) ; int b
= getNodeHeight ( root
-> right
) ; return a
> b
? a
+ 1 : b
+ 1 ; } return 0 ; } bool nodeIsBalance ( TreeNode
* node
) { int a
= getNodeHeight ( node
-> left
) ; int b
= getNodeHeight ( node
-> right
) ; if ( abs ( a
- b
) < 2 ) { return true ; } return false ; }
} ;
06 重建二叉樹
解題思路 前序遍歷結果的形式 [根節點][左子樹的前序遍歷結果][右子樹的前序遍歷結果] 中序遍歷結果的形式[左子樹的中序遍歷結果][根節點][右子樹的中序遍歷結果] 利用遞歸法構建,核心就是要找到將這個數據分成三部分的節點位置,通過根節點可以實現,然后遞歸構建二叉樹
class Solution {
public :
TreeNode
* buildTree ( vector
< int > & preorder
, vector
< int > & inorder
) { if ( preorder
. size ( ) == 0 ) { return NULL ; } int rootVal
= preorder
[ 0 ] ; int index
= 0 ; while ( rootVal
!= inorder
[ index
+ 0 ] ) { index
++ ; } TreeNode
* tree
= new TreeNode ( rootVal
) ; tree
-> left
= buildSonTree ( preorder
, 1 , index
, inorder
, 0 , index
- 1 ) ; tree
-> right
= buildSonTree ( preorder
, index
+ 1 , preorder
. size ( ) - 1 , inorder
, index
+ 1 , inorder
. size ( ) - 1 ) ; return tree
; } TreeNode
* buildSonTree ( vector
< int > & preorder
, int pStart
, int pEnd
, vector
< int > & inorder
, int iStart
, int iEnd
) { if ( pStart
> pEnd
) { return NULL ; } else { int rootVal
= preorder
[ pStart
] ; int index
= 0 ; while ( rootVal
!= inorder
[ index
+ iStart
] ) { index
++ ; } TreeNode
* tree
= new TreeNode ( rootVal
) ; tree
-> left
= buildSonTree ( preorder
, pStart
+ 1 , pStart
+ index
, inorder
, iStart
, iStart
+ index
- 1 ) ; tree
-> right
= buildSonTree ( preorder
, pStart
+ index
+ 1 , pEnd
, inorder
, iStart
+ index
+ 1 , iEnd
) ; return tree
; } return NULL ; }
} ;
07 二叉樹的最近公共祖先
解題思想 解法1:遞歸,從上往下逐漸查找,不斷縮小所在區域,最后鎖定位置 解法2:遞歸,利用剪枝的思想,方法一的優化
class Solution {
public : TreeNode
* lowestCommonAncestor ( TreeNode
* root
, TreeNode
* p
, TreeNode
* q
) { return findNearestTree ( root
, p
, q
) ; } void preFindTreeNode ( TreeNode
* root
, TreeNode
* p
, bool & find
) { if ( root
== NULL ) { return ; } else if ( root
== p
) { find
= true ; } preFindTreeNode ( root
-> left
, p
, find
) ; preFindTreeNode ( root
-> right
, p
, find
) ; } bool containTwoNode ( TreeNode
* root
, TreeNode
* p
, TreeNode
* q
) { bool findp
= false ; bool findq
= false ; preFindTreeNode ( root
, p
, findp
) ; preFindTreeNode ( root
, q
, findq
) ; if ( findq
& findp
) { return true ; } else { return false ; } } TreeNode
* findNearestTree ( TreeNode
* root
, TreeNode
* p
, TreeNode
* q
) { if ( containTwoNode ( root
-> left
, p
, q
) ) { return findNearestTree ( root
-> left
, p
, q
) ; } else if ( containTwoNode ( root
-> right
, p
, q
) ) { return findNearestTree ( root
-> right
, p
, q
) ; } else { return root
; } }
} ;
class Solution {
public : TreeNode
* lowestCommonAncestor ( TreeNode
* root
, TreeNode
* p
, TreeNode
* q
) { if ( ( root
== NULL ) || ( root
== p
) || ( root
== q
) ) { return root
; } TreeNode
* left
= lowestCommonAncestor ( root
-> left
, p
, q
) ; TreeNode
* right
= lowestCommonAncestor ( root
-> right
, p
, q
) ; if ( left
== NULL ) { return right
; } if ( right
== NULL ) { return left
; } return root
; }
} ;
class Solution {
public : TreeNode
* lowestCommonAncestor ( TreeNode
* root
, TreeNode
* p
, TreeNode
* q
) { while ( true ) { if ( ( root
-> val
> p
-> val
) & ( root
-> val
> q
-> val
) ) { root
= root
-> left
; continue ; } else if ( ( root
-> val
< p
-> val
) & ( root
-> val
< q
-> val
) ) { root
= root
-> right
; continue ; } else { return root
; } } }
} ;
08 二叉搜索樹的第k大節點
解題思路 解法1 : 中序遍歷 直接保存前k個最大值 解法2 中序遍歷利用利用一個計數器查找第k個最大值在這里插入代碼片
class Solution {
public :
int kthLargest ( TreeNode
* root
, int k
) { int value
; traverInOrderRightFirst ( root
, value
, k
) ; return value
; } void traverInOrderRightFirst ( TreeNode
* root
, int & value
, int & k
) { if ( ( root
== NULL ) || ( k
== 0 ) ) { return ; } traverInOrderRightFirst ( root
-> right
, value
, k
) ; if ( k
== 0 ) { return ; } value
= root
-> val
; k
-- ; traverInOrderRightFirst ( root
-> left
, value
, k
) ; }
} ;
10 從上到下打印二叉樹
解題思路 建立兩個棧,一個保存當前這一層的數據,另一個保存當前這一層的子節點數據
class Solution {
public : vector
< int > levelOrder ( TreeNode
* root
) { vector
< int > vecInt
; if ( root
== NULL ) { return vecInt
; } vector
< TreeNode
* > firstLevel
; vector
< TreeNode
* > secondLevel
; firstLevel
. push_back ( root
) ; while ( ! ( firstLevel
. empty ( ) & secondLevel
. empty ( ) ) ) { for ( auto node
: firstLevel
) { vecInt
. push_back ( node
-> val
) ; if ( node
-> left
!= NULL ) { secondLevel
. push_back ( node
-> left
) ; } if ( node
-> right
!= NULL ) { secondLevel
. push_back ( node
-> right
) ; } } firstLevel
. clear ( ) ; firstLevel
= secondLevel
; secondLevel
. clear ( ) ; } return vecInt
; }
} ;
11二叉搜索樹與雙向鏈表
解題思路 利用中序遍歷和兩個指針,pre和cur指針,分別指向上一個元素和當前元素
class Solution {
public : Node
* treeToDoublyList ( Node
* root
) { if ( root
== nullptr ) return nullptr ; dfs ( root
) ; head
-> left
= pre
; pre
-> right
= head
; return head
; } void dfs ( Node
* cur
) { if ( cur
== nullptr ) return ; else { dfs ( cur
-> left
) ; if ( pre
!= nullptr ) pre
-> right
= cur
; else { head
= cur
; } cur
-> left
= pre
; pre
= cur
; dfs ( cur
-> right
) ; } } private : Node
* pre
; Node
* head
;
} ;
12 序列化二叉樹
利用隊列實現先進先出 利用vector構建完全二叉樹。
class Codec {
public : string
serialize ( TreeNode
* root
) { string res
= "" ; if ( root
== NULL ) return "" ; queue
< TreeNode
* > my_queue
; my_queue
. push ( root
) ; TreeNode
* cur
= new TreeNode ( 0 ) ; while ( ! my_queue
. empty ( ) ) { int len
= my_queue
. size ( ) ; while ( len
-- ) { cur
= my_queue
. front ( ) ; my_queue
. pop ( ) ; if ( cur
== NULL ) { res
. push_back ( '$' ) ; } else { res
. append ( to_string ( cur
-> val
) ) ; } res
. push_back ( ',' ) ; if ( cur
!= NULL ) { my_queue
. push ( cur
-> left
) ; my_queue
. push ( cur
-> right
) ; } } } res
. pop_back ( ) ; return res
; } TreeNode
* deserialize ( string data
) { if ( data
. size ( ) == 0 ) return NULL ; int len
= data
. size ( ) ; int i
= 0 ; vector
< TreeNode
* > vec
; while ( i
< len
) { string str
= "" ; while ( i
< len
&& data
[ i
] != ',' ) { str
. push_back ( data
[ i
] ) ; i
++ ; } if ( str
== "$" ) { TreeNode
* temp
= NULL ; vec
. push_back ( temp
) ; } else { int temp
= std
:: stoi ( str
) ; TreeNode
* cur
= new TreeNode ( temp
) ; vec
. push_back ( cur
) ; } i
++ ; } int j
= 1 ; for ( int i
= 0 ; j
< vec
. size ( ) ; i
++ ) { if ( vec
[ i
] == NULL ) continue ; if ( j
< vec
. size ( ) ) vec
[ i
] -> left
= vec
[ j
++ ] ; if ( j
< vec
. size ( ) ) vec
[ i
] -> right
= vec
[ j
++ ] ; } return vec
[ 0 ] ; }
} ;
13從上到下層序打印二叉樹
解題思路 利用層序遍歷BFS加上兩個隊列或者棧等數據結構,注意每次都是從隊尾取數據,但是添加數據的順序要考慮好
# include <iostream>
# include <vector>
# include <deque> using namespace :: std
; struct TreeNode { int val
; TreeNode
* left
; TreeNode
* right
; TreeNode ( int x
) : val ( x
) , left ( NULL ) , right ( NULL ) { }
} ; class Solution {
public : vector
< vector
< int >> levelOrder ( TreeNode
* root
) { vector
< vector
< int >> res
; deque
< TreeNode
* > dTN1
; deque
< TreeNode
* > dTN2
; bool direction
= true ; dTN1
. push_back ( root
) ; while ( dTN1
. size ( ) != 0 ) { vector
< int > resTemp
; if ( direction
) { while ( dTN1
. size ( ) != 0 ) { TreeNode
* temp
= dTN1
. back ( ) ; resTemp
. push_back ( temp
-> val
) ; if ( temp
-> left
!= nullptr ) { dTN2
. push_back ( temp
-> left
) ; } if ( temp
-> right
!= nullptr ) { dTN2
. push_back ( temp
-> right
) ; } dTN1
. pop_back ( ) ; } direction
= ! direction
; } else { while ( dTN1
. size ( ) != 0 ) { TreeNode
* temp
= dTN1
. back ( ) ; resTemp
. push_back ( temp
-> val
) ; if ( temp
-> right
!= nullptr ) { dTN2
. push_back ( temp
-> right
) ; } if ( temp
-> left
!= nullptr ) { dTN2
. push_back ( temp
-> left
) ; } dTN1
. pop_back ( ) ; } direction
= ! direction
; } res
. push_back ( std
:: move ( resTemp
) ) ; dTN1
. clear ( ) ; dTN1
= std
:: move ( dTN2
) ; } return std
:: move ( res
) ; } } ; TreeNode
* root
= new TreeNode ( 1 ) ;
TreeNode
* node1L
= new TreeNode ( 2 ) ;
TreeNode
* node1R
= new TreeNode ( 3 ) ;
TreeNode
* node2L
= new TreeNode ( 4 ) ;
TreeNode
* node2R
= new TreeNode ( 5 ) ;
TreeNode
* node3L
= new TreeNode ( 6 ) ;
TreeNode
* node3R
= new TreeNode ( 7 ) ; int main ( )
{ root
-> left
= node1L
; root
-> right
= node1R
; node1R
-> left
= node2L
; node1R
-> right
= node2R
; node2L
-> left
= node3L
; node2L
-> right
= node3R
; Solution S
; vector
< vector
< int >> intVec
= S
. levelOrder ( root
) ; for ( int i
= 0 ; i
< intVec
. size ( ) ; i
++ ) { for ( int j
= 0 ; j
< intVec
[ i
] . size ( ) ; j
++ ) { std
:: cout
<< intVec
[ i
] [ j
] ; } std
:: cout
<< std
:: endl
; }
}
14 二叉搜索樹的后序遍歷序列
解法 利用遞歸的思想,關鍵是對每一層判斷是否滿足二叉樹。
class Solution {
public :
bool verifyPostorder ( vector
< int > & postorder
) { return isSatisfy ( postorder
, 0 , postorder
. size ( ) - 1 ) ; } bool isSatisfy ( vector
< int > & postorder
, int starti
, int endj
) { if ( ( ( endj
- starti
) < 1 ) ) { return true ; } for ( int j
= starti
; j
< endj
; j
++ ) { if ( postorder
[ j
] >= postorder
[ endj
] ) { for ( int k
= j
; k
< endj
; k
++ ) { if ( postorder
[ k
] <= postorder
[ endj
] ) { return false ; } } return ( isSatisfy ( postorder
, starti
, j
- 1 ) & isSatisfy ( postorder
, j
, endj
- 1 ) ) ; } } return isSatisfy ( postorder
, starti
, endj
- 1 ) ; }
} ;
15 二叉樹中和為某一值的路徑
解法一 直接遍歷一遍
class Solution {
public : vector
< vector
< int >> pathSum ( TreeNode
* root
, int target
) { BFSPath ( root
, target
) ; return pS
; } void BFSPath ( TreeNode
* root
, int target
) { if ( root
== nullptr ) { return ; } target
-= root
-> val
; path
. push_back ( root
-> val
) ; if ( ( target
== 0 ) & ( root
-> left
== nullptr ) & ( root
-> right
== nullptr ) ) { pS
. push_back ( path
) ; } BFSPath ( root
-> left
, target
) ; BFSPath ( root
-> right
, target
) ; path
. pop_back ( ) ; }
private : vector
< int > path
; vector
< vector
< int >> pS
; } ;
16數據流中的中位數
解題思路 這個問題難點在于數據是一點一點輸入的,一開始不知道數據量。破題處在于求中值,中值是一半數據的最大值,也是另一半的最小,使用堆結構可以解決這個問題
class MedianFinder {
public : priority_queue
< int , vector
< int > , less
< int >> maxHeap
; priority_queue
< int , vector
< int > , greater
< int >> minHeap
; MedianFinder ( ) { } void addNum ( int num
) { if ( maxHeap
. size ( ) == minHeap
. size ( ) ) { minHeap
. push ( num
) ; int top
= minHeap
. top ( ) ; minHeap
. pop ( ) ; maxHeap
. push ( top
) ; } else { maxHeap
. push ( num
) ; int top
= maxHeap
. top ( ) ; maxHeap
. pop ( ) ; minHeap
. push ( top
) ; } } double findMedian ( ) { if ( maxHeap
. size ( ) == minHeap
. size ( ) ) { return ( maxHeap
. top ( ) + minHeap
. top ( ) ) * 1.0 / 2 ; } else { return maxHeap
. top ( ) * 1.0 ; } }
} ;
總結
以上是生活随笔 為你收集整理的leetcode: 树 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。