二叉树为空意味着二叉树_不怕面试被问了!二叉树算法大盘点
作者 | BoCong-Deng
題圖 | 視覺中國
出品 | CSDN博客
樹結構對于程序員來說應該不陌生,特別是二叉樹,基本只要接觸算法這一類的都一定會碰到的,所以我打算通過一篇文章,對二叉樹結構的相關算法進行總結匯總,思路和代碼實現相結合,讓你不在懼怕二叉樹。(ps:后面我還想寫一篇樹結構的高級篇,就是多叉數,就是對我平時看算法論文碰到的一些新奇的算法,比如B樹、B+樹,還有我一種叫做Bed樹的新奇算法等等)
單純就是想分享技術博文,還想說一句就是,如果覺得有用,請點個關注、給個贊吧,也算對我來說是個寬慰,畢竟也得掉不少頭發,嘿嘿嘿。
下面的思路講解中,我會給出一個類偽代碼的思路,然后進行相關說明,也就是一種思路框架,有了思路框架,以后碰到問題就直接交給框架完成。本文主要說一下二叉搜索樹(Binary Search Tree,簡稱 BST),BST是一種很常用的的二叉樹。它的定義是:一個二叉樹中,任意節點的值要大于等于左子樹所有節點的值,且要小于等于右邊子樹的所有節點的值。如下就是一個符合定義的 BST:
后面如果遇到特殊的思路結構,如多叉樹,我會特別說明。首先我們先給出二叉樹的節點定義(這個定義應該不陌生吧,有刷算法題都會碰到)。
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
遞歸
不過這里要說明一點的是,在偽代碼中的“進行想要的操作”的位置,不一定就在我放置的位置,具體位置還需要我們根據不同的實際需求進行判斷。不過因為前中后序的遍歷,遞歸進入的時機應該需要和我的一樣。
先序遍歷
遍歷根節點,如果根節點為空,返回;否則,遍歷根節點,然后先序遍歷左子樹,再先序遍歷右子樹。
public void preorderTraverse(TreeNode root){System.out.print(node.val+" ");
preorderTraverse(root.left);
preorderTraverse(root.right);
}
中序遍歷
路過根節點,如果根節點為空,返回;否則,中序遍歷左子樹,然后遍歷根節點,再中序遍歷右子樹。
public void inorderTraverse(TreeNode root){inorderTraverse(root.left);
System.out.print(node.val+" ");
inorderTraverse(root.right);
}
后序遍歷
路過根節點,如果根節點為空,返回;否則,后序遍歷左子樹,再后序遍歷右子樹,最后遍歷根節點。
public void postorderTraverse(TreeNode root){postorderTraverse(root.left);
postorderTraverse(root.right);
System.out.print(node.val+" ");
}
迭代(非遞歸)
我們使用迭代的思想,其實就是利用循環和棧來模擬遞歸的操作,上面遞歸的操作,其實就是一個不斷將自己以及左右子節點進行壓棧和出棧的過程,如果理解了上面的算法下面的算法就好理解了
前序遍歷
public List preorderTraversal(TreeNode root) {List list = new ArrayList<>;
if(root==){
return list;
}
Stack stack = new Stack<>;
stack.push(root);
while(!stack.isEmpty){
TreeNode res = stack.pop;
if(res.right != )
stack.push(res.right);
if(res.left != )
stack.push(res.left);
list.add(res.val);
}
return list;
}
中序遍歷
public List inorderTraversal(TreeNode root) {List list = new ArrayList<>;
if(root==){
return list;
}
Stack stack = new Stack<>;
TreeNode curr = root;
while(curr != || !(stack.isEmpty)){
if(curr!= ){
stack.push(curr);
curr = curr.left;
}else{
curr = stack.pop;
list.add(curr.val);
curr = curr.right;
}
}
return list;
}
后序遍歷
我們可以很簡單的實現另一種遍歷:”根->右->左“遍歷。雖然這種遍歷沒有名字,但是他是后序遍歷的反序。所以我們可以利用兩個棧,利用棧的LIFO特點,來實現后續遍歷。
public List preorderTraversal(TreeNode root) {List list = new ArrayList<>;
if(root==){
return list;
}
Stack stack = new Stack<>;
stack.push(root);
while(!stack.isEmpty){
TreeNode res = stack.pop;
if(res.left != )
stack.push(res.left);
if(res.right != )
stack.push(res.right);
list.add(res.val);
}
list.reserve;
return list;
}
深度優先搜索(DFS)
其實,二叉樹的先序遍歷,中序遍歷,后序遍歷,都是深度優先搜索,深搜是一種思想,并不具體指代實現方式,你可以使用遞歸,也可以使用棧來實現,所以上面提到的都是深度優先搜索的實現方式,畢竟“深度優先”嘛。
那在這里我就是提幾個實際的應用的例子,加深一下印象。
二叉樹的最大深度
public int maxDepth(TreeNode root) {if(root==){
return 0;
}
int left = maxDepth(root.left);
int right = maxDepth(root.right);
return Math.max(left,right)+1;
}
二叉樹的鏡像
public void Mirror(TreeNode root) {if(root!=){
if(root.left!= || root.right!= ){
TreeNode temp =root.left;
root.left=root.right;
root.right=temp;
}
Mirror(root.left);
Mirror(root.right);
}
}
對稱二叉樹
boolean isSymmetrical(TreeNode pRoot){if(pRoot == )
return true;
return real(pRoot.left,pRoot.right);
}
public boolean real(TreeNode root1,TreeNode root2){
if(root1 == && root2 == ){
return true;
}
if(root1 == || root2 == ){
return false;
}
if(root1.val != root2.val){
return false;
}
return real(root1.left,root2.right)&&real(root1.right,root2.left);
}
路徑總和
public class Solution {private ArrayList list = new ArrayList;
private ArrayList> listAll = new ArrayList>;
public ArrayList> FindPath(TreeNode root,int target) {
if(root == )
return listAll;
list.add(root.val);
target -= root.val;
if(target == 0 && root.left== && root.right == ){
listAll.add(new ArrayList(list));
}
FindPath(root.left,target);
FindPath(root.right,target);
list.remove(list.size-1);
return listAll;
}
}
重建二叉樹
public TreeNode reConstructBinaryTree(int [] pre,int [] in) {return reConstructBinaryTree(pre,0,pre.length-1,in,0,in.length-1);
}
public TreeNode reConstructBinaryTree(int [] pre,int startpre,int endpre,int [] in,int startin,int endin){
if(startpre > endpre || startin > endin){
return ;
}
TreeNode root = new TreeNode(pre[startpre]);
for(int i =startin;i<=endin;i++){
if(in[i] == pre[startpre]){
root.left = reConstructBinaryTree(pre,startpre+1,startpre+i-startin,in,startin,i-1);
root.right = reConstructBinaryTree(pre,startpre+i-startin+1,endpre,in,i+1,endin);
}
}
return root;
}
二叉搜索樹的最近公共祖先
class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == || root == p || root == q){
return root;
}
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
if(left!= && right!=){
return root;
}
return left!=?left:right;
}
}
二叉樹的序列化和反序列化
序列化:public String serialize(TreeNode root) {
if (root == ) {
return ;
}
// 利用二叉樹的層次遍歷方式進行序列化
StringBuilder res = new StringBuilder;
LinkedList queue = new LinkedList<>;
queue.add(root);
while (!queue.isEmpty) {
TreeNode node = queue.remove;
if (node != ) {
res.append(node.val).append(
總結
以上是生活随笔為你收集整理的二叉树为空意味着二叉树_不怕面试被问了!二叉树算法大盘点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: v8声卡怎么录制唱歌_V8声卡坑爹?想买
- 下一篇: StringBuffer和StringB