二叉樹的遞回遍歷
遞回的三要素
1.遞回函式的引數和回傳值
2.遞回出口
3.單層遞回的邏輯
144. 二叉樹的前序遍歷
給你二叉樹的根節點 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<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
preoder(root,result);
return result;
}
public void preoder(TreeNode node,List<Integer> result){
if (node==null){
return;
}
result.add(node.val);//前序遍歷:中、左、右
preoder(node.left,result);
preoder(node.right,result);
}
}
94. 二叉樹的中序遍歷
給定一個二叉樹的根節點 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<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList();
inorder(root,result);
return result;
}
public void inorder(TreeNode node, List<Integer> result){
if(node==null){
return;
}
inorder(node.left,result);//中序遍歷:左、中、右
result.add(node.val);
inorder(node.right,result);
}
}
145. 二叉樹的后序遍歷
給你一棵二叉樹的根節點 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<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList();
postorder(root,result);
return result;
}
public void postorder(TreeNode node,List<Integer> result){
if(node==null){
return;
}
postorder(node.left,result);//后序遍歷:左、右、中
postorder(node.right,result);
result.add(node.val);
}
}
二叉樹的迭代遍歷
用堆疊操作,遞回也是用堆疊實作的嘛??
144. 二叉樹的前序遍歷
給你二叉樹的根節點 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<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();//結果串列
Stack<TreeNode> stack = new Stack<>();
if(root==null){
return result;
}
stack.push(root);//先把根節點加到堆疊中去
while (!stack.empty()){
TreeNode node = stack.pop();//從堆疊中彈出一個結點來進行操作
result.add(node.val);//彈出的元素加到結果串列中
if(node.right!=null){
stack.push(node.right);//右孩子不空就進堆疊
}
if(node.left!=null){
stack.push(node.left);//左孩子不空就進堆疊
}
}
return result;
}
}
- 妙蛙種子吃了妙脆角,妙到家啦
145. 二叉樹的后序遍歷
給你一棵二叉樹的根節點 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<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();//結果串列
Stack<TreeNode> stack = new Stack<>();
if(root==null){
return result;
}
stack.push(root);//先把根節點加到堆疊中去
while (!stack.empty()){
TreeNode node = stack.pop();//從堆疊中彈出一個結點來進行操作
result.add(node.val);//彈出的元素加到結果串列中
if(node.left!=null){
stack.push(node.left);//左孩子不空就進堆疊
}
if(node.right!=null){
stack.push(node.right);//右孩子不空就進堆疊
}
}
Collections.reverse(result);
return result;
}
}
Collections.reverse(result) 鏈表反轉
- 這題和前序遍歷十分相似,就是入堆疊順序不一樣,畫圖找一下順序,改前序遍歷的代碼就可啦
94. 二叉樹的中序遍歷
給定一個二叉樹的根節點 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<Integer> inorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();//結果串列
Stack<TreeNode> stack = new Stack<>();
if(root==null){
return result;
}
TreeNode cur = root;//取到根結點
while (cur != null || !stack.isEmpty()){
if (cur != null){
stack.push(cur);//放入堆疊中
cur = cur.left;//把當前結點的左孩子賦給當前結點
}else{
cur = stack.pop();//彈出堆疊中的結點
result.add(cur.val);//放入結果集中
cur = cur.right;//把當前結點的右孩子賦給當前結點(左邊已經遍歷完了,上一步也把中間放入結果集中,該右邊了)
}
}
return result;
}
}
二叉樹的層序遍歷
也就是廣度優先遍歷啦
102.二叉樹的層序遍歷
給你二叉樹的根節點 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<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();//外層鏈表
Queue<TreeNode> que = new LinkedList<>();//新建一個佇列
if (root == null) {
return res;
}
que.add(root);//把根節點放入佇列
while (!que.isEmpty()){
//當佇列不為空時
ArrayList<Integer> item = new ArrayList<>();//內層鏈表
int size = que.size();//佇列的大小
while (size>0){
TreeNode node = que.poll();//彈出當前結點
if(node.left!=null){que.add(node.left);}//把當前結點的左孩子加進去(如果有的話)
if(node.right!=null){que.add(node.right);}//把當前結點的右孩子加進去(如果有的話)
item.add(node.val);//當前結點加到鏈表
size--;
}
res.add(item);//內層鏈表加入到外層鏈表中
}
return res;
}
}
下面是一堆層序遍歷的題
107. 二叉樹的層序遍歷 II
給你二叉樹的根節點 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<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();//外層鏈表
Queue<TreeNode> que = new LinkedList<TreeNode>();//佇列
if(root==null)return res;
que.add(root);//把根結點放入佇列
while (!que.isEmpty()){
List<Integer> item = new ArrayList<>();
int size = que.size();
while (size > 0) {
TreeNode node = que.poll();//佇列中彈出一個結點
item.add(node.val);
if(node.left!=null){que.add(node.left);}
if(node.right!=null){que.add(node.right);}
size--;
}
res.add(item);
}
Collections.reverse(res);
return res;
}
}
199. 二叉樹的右視圖
給定一個二叉樹的 根節點 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<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if(root==null)return res;
que.add(root);//根結點不為空,放入佇列
while (!que.isEmpty()){
List<Integer> item = new ArrayList<>();
int size = que.size();
while (size>0){
TreeNode node = que.poll();
item.add(node.val);
if(node.left!=null){que.add(node.left);}
if(node.right!=null){que.add(node.right);}
size--;
}
Integer i = item.get(item.size() - 1);
res.add(i);
}
return res;
}
}
637. 二叉樹的層平均值
給定一個非空二叉樹的根節點 root , 以陣列的形式回傳每一層節點的平均值,與實際答案相差 10-5 以內的答案可以被接受,
/**
* 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<Double> averageOfLevels(TreeNode root) {
List<Double> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if(root==null)return res;
que.add(root);
while (!que.isEmpty()){
int size = que.size();
double x = 0;
double sum = 0;
int count = size;
while (size>0){
TreeNode node = que.poll();
sum += node.val;
if(node.left!=null){que.add(node.left);}
if(node.right!=null){que.add(node.right);}
size--;
}
x = sum/count;
res.add(x);
}
return res;
}
}
429. 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 List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> res = new ArrayList<>();//外層鏈表
Queue<Node> que = new LinkedList<>();//新建一個佇列
if (root == null) {
return res;
}
que.add(root);//把根節點放入佇列
while (!que.isEmpty()){
//當佇列不為空時
ArrayList<Integer> item = new ArrayList<>();//內層鏈表
int size = que.size();//佇列的大小
while (size>0){
Node node = que.poll();//彈出當前結點
//當前結點加到鏈表
if(node.children!=null){
for (Node child : node.children) {
que.add(child);
}
}
item.add(node.val);
size--;
}
res.add(item);//內層鏈表加入到外層鏈表中
}
return res;
}
}
- 添加子結點到佇列的操作有點不一樣
515. 在每個樹行中找最大值
給定一棵二叉樹的根節點 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<Integer> largestValues(TreeNode root) {
List<Integer> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if(root==null){
return res;
}
que.add(root);
while(!que.isEmpty()){
int size = que.size();
int x = Integer.MIN_VALUE;
while(size>0){
TreeNode node = que.poll();
x = node.val>x ? node.val : x;
if(node.left!=null){que.add(node.left);}
if(node.right!=null){que.add(node.right);}
size--;
}
res.add(x);
}
return res;
}
}
116. 填充每個節點的下一個右側節點指標
給定一個 完美二叉樹 ,其所有葉子節點都在同一層,每個父節點都有兩個子節點,二叉樹定義如下:
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每個 next 指標,讓這個指標指向其下一個右側節點,如果找不到下一個右側節點,則將 next 指標設定為 NULL,
初始狀態下,所有 next 指標都被設定為 NULL,
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<>();
if (root == null) {
return root;
}
que.add(root);
while (que.size() > 0) {
int size = que.size();
Node node = que.poll();
if (node.left != null) {que.add(node.left);}
if (node.right != null) {que.add(node.right);}
for (int i = 1; i < size; i++) {
Node next = que.poll();//彈出該層剩余元素
if (next.left != null) que.add(next.left);
if (next.right != null) que.add(next.right);
node.next = next;
node = next;
}
}
return root;
}
}
117. 填充每個節點的下一個右側節點指標 II
給定一個二叉樹
struct Node {
int val;
Node *left;
Node *right;
Node *next;
}
填充它的每個 next 指標,讓這個指標指向其下一個右側節點,如果找不到下一個右側節點,則將 next 指標設定為 NULL,
初始狀態下,所有 next 指標都被設定為 NULL,
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
Queue<Node> que = new LinkedList<>();
if (root == null) {
return root;
}
que.add(root);
while (que.size() > 0) {
int size = que.size();
Node node = que.poll();
if (node.left != null) {que.add(node.left);}
if (node.right != null) {que.add(node.right);}
for (int i = 1; i < size; i++) {
Node next = que.poll();//彈出該層剩余元素
if (next.left != null) que.add(next.left);
if (next.right != null) que.add(next.right);
node.next = next;
node = next;
}
}
return root;
}
}
- 離大譜,這題代碼跟上題一樣,一模一樣
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) {
Queue<TreeNode> que = new LinkedList<>();//新建一個佇列
if (root == null) {
return 0;
}
que.add(root);//把根節點放入佇列
int count = 0;
while (!que.isEmpty()) {
//當佇列不為空時
count++;
ArrayList<Integer> item = new ArrayList<>();//內層鏈表
int size = que.size();//佇列的大小
while (size > 0) {
TreeNode node = que.poll();//彈出當前結點
if (node.left != null) {
que.add(node.left);
}//把當前結點的左孩子加進去(如果有的話)
if (node.right != null) {
que.add(node.right);
}//把當前結點的右孩子加進去(如果有的話)
size--;
}
}
return count;
}
}
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) {
Queue<TreeNode> que = new LinkedList<>();//新建一個佇列
if (root == null) {
return 0;
}
que.add(root);//把根節點放入佇列
int count = 0;
while (!que.isEmpty()) {
//當佇列不為空時
count++;
ArrayList<Integer> item = new ArrayList<>();//內層鏈表
int size = que.size();//佇列的大小
while (size > 0) {
TreeNode node = que.poll();//彈出當前結點
if (node.left != null) {
que.add(node.left);
}//把當前結點的左孩子加進去(如果有的話)
if (node.right != null) {
que.add(node.right);
}//把當前結點的右孩子加進去(如果有的話)
if(node.left==null&&node.right==null){
return count;
}
size--;
}
}
return count;
}
}
總結
-
通過今天的題目大致掌握二叉樹的結構,深度優先遍歷方面掌握前序、中序、后續的遞回實作和迭代實作,掌握廣度優先遍歷的模板(寫了十道層序遍歷的題目,就算是小豬也會了??
-
今天的題目自己寫出來的不多,除了最后幾道改模板的題,不知道是因為天太冷還是頭上戴的蝴蝶結封印了我的智慧的??
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/511965.html
標籤:其他
下一篇:安裝pcov遇到的問題
