本文首發於個人我的博客:尾尾部落java
徹底二叉樹:若二叉樹的高度是h,除第h層以外,其餘(1~h-1)層的節點數都達到了最大個數,而且第h層的節點都連續的集中在最左邊。想到點什麼沒?實際上,徹底二叉樹和堆聯繫比較緊密哈~~~node
滿二叉樹:除最後一層外,每一層上的全部節點都有兩個子節點,最後一層都是葉子節點。app
哈夫曼樹:給定n個權值做爲n的葉子結點,構造一棵二叉樹,若帶權路徑長度達到最小,稱這樣的二叉樹爲最優二叉樹,也稱爲哈夫曼樹(Huffman tree)。函數
二叉排序樹:又稱二叉查找樹(Binary Search Tree),亦稱二叉搜索樹。二叉排序樹或者是一棵空樹,或者是具備下列性質的二叉樹:post
二分查找的時間複雜度是O(log(n)),最壞狀況下的時間複雜度是O(n)(至關於順序查找)測試
平衡二叉樹:又稱 AVL 樹。平衡二叉樹是二叉搜索樹的進化版,所謂平衡二叉樹指的是,左右兩個子樹的高度差的絕對值不超過 1。ui
紅黑樹:紅黑樹是每一個節點都帶顏色的樹,節點顏色或是紅色或是黑色,紅黑樹是一種查找樹。紅黑樹有一個重要的性質,從根節點到葉子節點的最長的路徑很少於最短的路徑的長度的兩倍。對於紅黑樹,插入,刪除,查找的複雜度都是O(log N)。this
遞歸解法: (1)若是二叉樹爲空,節點個數爲0 (2)若是不爲空,二叉樹節點個數 = 左子樹節點個數 + 右子樹節點個數 + 1 參考代碼以下:spa
public static int getNodeNumRec(TreeNode root) {
if (root == null) {
return 0;
}
return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;
}
複製代碼
劍指offer:二叉樹的深度 遞歸解法: (1)若是二叉樹爲空,二叉樹的深度爲0 (2)若是二叉樹不爲空,二叉樹的深度 = max(左子樹深度, 右子樹深度) + 1 參考代碼以下:3d
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */
class Solution {
public int maxDepth(TreeNode root) {
if(root == null)
return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right))+1;
}
}
複製代碼
LeetCode:Minimum Depth of Binary Tree 給定一個二叉樹,找出其最小深度。 最小深度是從根節點到最近葉子節點的最短路徑上的節點數量。
class Solution {
public int minDepth(TreeNode root) {
if(root == null)
return 0;
int left = minDepth(root.left);
int right = minDepth(root.right);
return (left == 0 || right == 0) ? left + right + 1 : Math.min(left, right) + 1;
}
}
複製代碼
LeetCode:Binary Tree Preorder Traversal 給定二叉樹,返回其節點值的前序遍歷。
根 - 左 - 右
ArrayList<Integer> preOrderReverse(TreeNode root){
ArrayList<Integer> result = new ArrayList<Integer>();
preOrder(root, result);
return result;
}
void preOrder(TreeNode root,ArrayList<Integer> result){
if(root == null){
return;
}
result.add(root.val);
preOrder(root.left, result);
preOrder(root.right, result);
}
複製代碼
法一:
import java.util.Stack;
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
LinkedList<Integer> res = new LinkedList<>();
if(root == null)
return res;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while(!stack.isEmpty()){
TreeNode node = stack.pop();
res.add(node.val);
if(node.right != null){
stack.push(node.right);
}
if(node.left != null){
stack.push(node.left);
}
}
return res;
}
}
複製代碼
法二:
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null)
return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
while(cur != null || !stack.isEmpty()){
if(cur!=null){
res.add(cur.val);
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
cur = cur.right;
}
}
return res;
}
}
複製代碼
LeetCode:Binary Tree Inorder Traversal 給定二叉樹,返回其節點值的中序遍歷。
左 - 根 - 右
void inOrder(TreeNode root,ArrayList<Integer> result){
if(root == null){
return;
}
preOrder(root.left, result);
result.add(root.val);
preOrder(root.right, result);
}
複製代碼
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null)
return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
while(!stack.isEmpty() || cur != null){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
}
return res;
}
}
複製代碼
Leetcode:Binary Tree Postorder Traversal 給定二叉樹,返回其節點值的後序遍歷。
左 - 右 - 根
void inOrder(TreeNode root,ArrayList<Integer> result){
if(root == null){
return;
}
preOrder(root.left, result);
preOrder(root.right, result);
result.add(root.val);
}
複製代碼
方法一:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<Integer> ans = new LinkedList<>();
Stack<TreeNode> stack = new Stack<>();
if (root == null) return ans;
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
//採用逆序插入的方式
ans.addFirst(cur.val);
if (cur.left != null) {
stack.push(cur.left);
}
if (cur.right != null) {
stack.push(cur.right);
}
}
return ans;
}
}
複製代碼
方法二:
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null)
return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
TreeNode visited = null;
while(!stack.isEmpty() || cur != null){
if(cur != null){
stack.push(cur);
cur = cur.left;
}else{
cur = stack.peek();
if(cur.right != null && cur.right != visited){
cur = cur.right;
}else{
res.add(cur.val);
visited = cur;
stack.pop();
cur = null;
}
}
}
return res;
}
}
複製代碼
方法三(推薦):
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
LinkedList<Integer> result = new LinkedList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode p = root;
while(!stack.isEmpty() || p != null) {
if(p != null) {
stack.push(p);
result.addFirst(p.val); // Reverse the process of preorder
p = p.right; // Reverse the process of preorder
} else {
TreeNode node = stack.pop();
p = node.left; // Reverse the process of preorder
}
}
return result;
}
}
複製代碼
LeetCode:Binary Tree Level Order Traversal 劍指offer:從上往下打印二叉樹 劍指offer:把二叉樹打印成多行 給定二叉樹,返回其節點值的級別順序遍歷。
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<List<Integer>>();
if(root == null)
return res;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
TreeNode cur = null;
queue.add(root);
while(!queue.isEmpty()){
ArrayList<Integer> level = new ArrayList<Integer>();
int l = queue.size();
for(int i=0; i<l;i++){
cur = queue.poll();
level.add(cur.val);
if(cur.left != null)
queue.add(cur.left);
if(cur.right != null)
queue.add(cur.right);
}
res.add(level);
}
return res;
}
}
複製代碼
LeetCode:Binary Tree Level Order Traversal II 給定二叉樹,返回其節點值的自下而上級別順序遍歷。
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> res = new LinkedList<>();
Queue<TreeNode> queue = new LinkedList<>();
if(root == null)
return res;
queue.add(root);
while(!queue.isEmpty()){
int count = queue.size();
List<Integer> temp = new LinkedList<>();
for(int i=0; i<count; i++){
TreeNode node = queue.poll();
temp.add(node.val);
if(node.left != null)
queue.add(node.left);
if(node.right != null)
queue.add(node.right);
}
// 每次都添加到第一個位置
res.add(0, temp);
}
return res;
}
}
複製代碼
劍指offer:按之字形順序打印二叉樹 請實現一個函數按照之字形打印二叉樹,即第一行按照從左到右的順序打印,第二層按照從右至左的順序打印,第三行按照從左到右的順序打印,其餘行以此類推。
設兩個棧,s2存放奇數層,s1存放偶數層 遍歷s2節點的同時按照左子樹、右子樹的順序加入s1, 遍歷s1節點的同時按照右子樹、左子樹的順序加入s2
import java.util.ArrayList;
import java.util.Stack;
/* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int val) { this.val = val; } } */
public class Solution {
public ArrayList<ArrayList<Integer> > Print(TreeNode pRoot) {
ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer> >();
Stack<TreeNode> s1 = new Stack<TreeNode>();
Stack<TreeNode> s2 = new Stack<TreeNode>();
int flag = 1;
if(pRoot == null)
return res;
s2.push(pRoot);
ArrayList<Integer> temp = new ArrayList<Integer>();
while(!s1.isEmpty() || !s2.isEmpty()){
if(flag % 2 != 0){
while(!s2.isEmpty()){
TreeNode node = s2.pop();
temp.add(node.val);
if(node.left != null){
s1.push(node.left);
}
if(node.right != null){
s1.push(node.right);
}
}
}
if(flag % 2 == 0){
while(!s1.isEmpty()){
TreeNode node = s1.pop();
temp.add(node.val);
if(node.right != null){
s2.push(node.right);
}
if(node.left != null){
s2.push(node.left);
}
}
}
res.add(new ArrayList<Integer>(temp));
temp.clear();
flag ++;
}
return res;
}
}
複製代碼
void get_k_level_number(TreeNode root, int k){
if(root == null || k <=0){
return 0;
}
if(root != null && k == 1){
return 1;
}
return get_k_level_number(root.left, k-1) + get_k_level_number(root.right, k-1);
}
複製代碼
void get_k_level_leaf_number(TreeNode root, int k){
if(root == null || k <=0){
return 0;
}
if(root != null && k == 1){
if(root.left == null && root.right == null)
return 1;
else
return 0;
}
return get_k_level_number(root.left, k-1) + get_k_level_number(root.right, k-1);
}
複製代碼
LeetCode:Same Tree 給定兩個二叉樹,編寫一個函數來檢查它們是否相同。
遞歸解法: (1)若是兩棵二叉樹都爲空,返回真 (2)若是兩棵二叉樹一棵爲空,另外一棵不爲空,返回假 (3)若是兩棵二叉樹都不爲空,若是對應的左子樹和右子樹都同構返回真,其餘返回假
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null)
return true;
if(p == null || q == null)
return false;
if(p.val == q.val)
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
return false;
}
}
複製代碼
LeetCode:Balanced Binary Tree 給定二叉樹,肯定它是不是高度平衡的。 對於此問題,高度平衡二叉樹定義爲: 一個二叉樹,其中每一個節點的兩個子樹的深度差不相差超過1。
遞歸解法: (1)若是二叉樹爲空,返回真 (2)若是二叉樹不爲空,若是左子樹和右子樹高度相差不大於1且左子樹和右子樹都是AVL樹,返回真,其餘返回假
class Solution {
public boolean isBalanced(TreeNode root) {
if(root == null)
return true;
return Math.abs(maxHigh(root.left) - maxHigh(root.right)) <= 1
&& isBalanced(root.left) && isBalanced(root.right);
}
public int maxHigh(TreeNode root){
if(root == null)
return 0;
return Math.max(maxHigh(root.left), maxHigh(root.right))+1;
}
}
複製代碼
劍指offer:二叉樹的鏡像 LeetCode:Invert Binary Tree 反轉二叉樹
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null)
return root;
TreeNode node = root.left;
root.left = invertTree(root.right);
root.right = invertTree(node);
return root;
}
}
複製代碼
劍指offer:對稱的二叉樹 LeetCode:Symmetric Tree 給定一個二叉樹,檢查它是不是鏡像對稱的。
![]()
class Solution {
public boolean isSymmetric(TreeNode root) {
return root == null || isSymmetricHelper(root.left, root.right);
}
public boolean isSymmetricHelper(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;
return isSymmetricHelper(left.left, right.right) && isSymmetricHelper(left.right, right.left);
}
}
複製代碼
LeetCode:Lowest Common Ancestor of a Binary Tree 給定二叉樹,找到樹中兩個給定節點的最低共同祖先(LCA)。
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 && right != null)
return root;
return left == null ? right : left;
}
}
複製代碼
LeetCode:Lowest Common Ancestor of a Binary Search Tree 給定一個二叉搜索樹, 找到該樹中兩個指定節點的最近公共祖先。 百度百科中最近公共祖先的定義爲:「對於有根樹 T 的兩個結點 p、q,最近公共祖先表示爲一個結點 x,知足 x 是 p、q 的祖先且 x 的深度儘量大(一個節點也能夠是它本身的祖先)。」
左子樹
<
根節點
<
右子樹
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root.val > p.val && root.val > q.val){
return lowestCommonAncestor(root.left, p, q);
}
else if(root.val < p.val && root.val < q.val){
return lowestCommonAncestor(root.right, p, q);
}
else{
return root;
}
}
}
複製代碼
LeetCode:Diameter of Binary Tree 給定一棵二叉樹,你須要計算它的直徑長度。一棵二叉樹的直徑長度是任意兩個結點路徑長度中的最大值。這條路徑可能穿過根結點。
class Solution {
private int path = 0;
public int diameterOfBinaryTree(TreeNode root) {
diamHelper(root);
return path;
}
private int diamHelper(TreeNode root){
if(root == null)
return 0;
int left = diamHelper(root.left);
int right = diamHelper(root.right);
path = Math.max(path, left + right);
return Math.max(left, right) + 1;
}
}
複製代碼
劍指offer:重建二叉樹 LeetCode:Construct Binary Tree from Preorder and Inorder Traversal 根據一棵樹的前序遍歷與中序遍歷構造二叉樹。
class Solution {
public TreeNode buildTree(int[] preorder, int[] inorder) {
if(preorder.length == 0 || inorder.length == 0)
return null;
return buildTreeHelper(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
public TreeNode buildTreeHelper(int[] preorder, int pre_start, int pre_end, int[] inorder, int in_start, int in_end){
if(pre_start > pre_end || in_start > in_end)
return null;
TreeNode root = new TreeNode(preorder[pre_start]);
for(int i = in_start; i <= in_end; i++){
if(inorder[i] == preorder[pre_start]){
// 左子樹的長度:i-is
root.left = buildTreeHelper(preorder, pre_start + 1, pre_start + i - in_start, inorder, in_start, i - 1);
root.right = buildTreeHelper(preorder, pre_start + i - in_start + 1, pre_end, inorder, i + 1, in_end);
}
}
return root;
}
}
複製代碼
LeetCode:Construct Binary Tree from Inorder and Postorder Traversal 根據一棵樹的中序遍歷與後序遍歷構造二叉樹。
class Solution {
public TreeNode buildTree(int[] inorder, int[] postorder) {
if(inorder.length == 0 || postorder.length == 0)
return null;
return buildTreeHelper(inorder, 0, inorder.length - 1, postorder, 0, postorder.length - 1);
}
public TreeNode buildTreeHelper(int[] inorder, int in_start, int in_end, int[] postorder, int post_start, int post_end){
if(in_start > in_end || post_start > post_end)
return null;
TreeNode root = new TreeNode(postorder[post_end]);
for(int i = in_start; i <= in_end; i++){
if(inorder[i] == postorder[post_end]){
root.left = buildTreeHelper(inorder, in_start, i - 1, postorder, post_start, post_start + i - in_start - 1);
root.right = buildTreeHelper(inorder, i + 1, in_end, postorder, post_start + i - in_start, post_end - 1);
}
}
return root;
}
}
複製代碼
提示:根據前序和後序遍歷沒法構造出惟一的二叉樹
徹底二叉樹是指最後一層左邊是滿的,右邊可能慢也不能不滿,而後其他層都是滿的,根據這個特性,利用層遍歷。若是咱們當前遍歷到了NULL結點,若是後續還有非NULL結點,說明是非徹底二叉樹。
class Solution {
public boolean _CheckCompleteTree(TreeNode root) {
Queue<TreeNode> queue = LinkedList<>();
if(root == null)
return true;
queue.add(root);
while(!queue.isEmpty()){
TreeNode node = queue.pop();
if(node != null){
if(flag == true)
return false;
queue.add(node.left);
queue.add(node.right);
}else{
flag = true;
}
}
return true;
}
}
複製代碼
劍指offer:樹的子結構 輸入兩棵二叉樹A,B,判斷B是否是A的子結構。
public class Solution {
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
if(root1 == null || root2 == null){
return false;
}
return IsSubtree(root1, root2) ||
HasSubtree(root1.left, root2) ||
HasSubtree(root1.right, root2);
}
public boolean IsSubtree(TreeNode root1, TreeNode root2){
//要先判斷roo2, 否則{8,8,7,9,2,#,#,#,#,4,7},{8,9,2}這個測試用例通不過。
if(root2 == null)
return true;
if(root1 == null)
return false;
if(root1.val == root2.val){
return IsSubtree(root1.left, root2.left) &&
IsSubtree(root1.right, root2.right);
}else
return false;
}
}
複製代碼
劍指offer:二叉樹中和爲某一值的路徑 輸入一顆二叉樹和一個整數,打印出二叉樹中結點值的和爲輸入整數的全部路徑。路徑定義爲從樹的根結點開始往下一直到葉結點所通過的結點造成一條路徑。
public class Solution {
ArrayList<ArrayList<Integer> > res = new ArrayList<ArrayList<Integer> >();
ArrayList<Integer> temp = new ArrayList<Integer>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if(root == null)
return res;
target -= root.val;
temp.add(root.val);
if(target == 0 && root.left == null && root.right == null)
res.add(new ArrayList<Integer>(temp));
else{
FindPath(root.left, target);
FindPath(root.right, target);
}
temp.remove(temp.size()-1);
return res;
}
}
複製代碼
劍指offer:二叉樹的下一個結點 給定一個二叉樹和其中的一個結點,請找出中序遍歷順序的下一個結點而且返回。注意,樹中的結點不只包含左右子結點,同時包含指向父結點的指針。
public class Solution {
public TreeLinkNode GetNext(TreeLinkNode pNode) {
if(pNode == null){
return null;
}
if(pNode.right != null){
TreeLinkNode node = pNode.right;
while(node.left != null){
node = node.left;
}
return node;
}
while(pNode.next != null){
TreeLinkNode root = pNode.next;
if(pNode == root.left)
return root;
pNode = root;
}
return null;
}
}
複製代碼
劍指offer:序列化二叉樹 LeetCode:Serialize and Deserialize Binary Tree 請實現兩個函數,分別用來序列化和反序列化二叉樹
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null)
return "#,";
StringBuffer res = new StringBuffer(root.val + ",");
res.append(serialize(root.left));
res.append(serialize(root.right));
return res.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String [] d = data.split(",");
Queue<String> queue = new LinkedList<>();
for(int i = 0; i < d.length; i++){
queue.offer(d[i]);
}
return pre(queue);
}
public TreeNode pre(Queue<String> queue){
String val = queue.poll();
if(val.equals("#"))
return null;
TreeNode node = new TreeNode(Integer.parseInt(val));
node.left = pre(queue);
node.right = pre(queue);
return node;
}
}
複製代碼
劍指offer:二叉搜索樹的第k個結點 給定一棵二叉搜索樹,請找出其中的第k小的結點。例如, (5,3,7,2,4,6,8)中,按結點數值大小順序第三小結點的值爲4。
class Solution {
public int kthSmallest(TreeNode root, int k) {
if(root == null)
return Integer.MIN_VALUE;
Stack<TreeNode> stack = new Stack<>();
int count = 0;
TreeNode p = root;
while(p != null || !stack.isEmpty()){
if(p != null){
stack.push(p);
p = p.left;
}else{
TreeNode node = stack.pop();
count ++;
if(count == k)
return node.val;
p = node.right;
}
}
return Integer.MIN_VALUE;
}
}
複製代碼