算法-树结构
一、概述
一维结构:数组、链表、跳表、栈、队列等,这些结构都是 线性存储结构。
二维结构:树、图,是一种非线性存储结构,存储的是具有 “一对多”关系的数据元素的集合。
树 Tree
- 结点:使用树结构存储的每一个数据元素都被称为“结点”。
- 根结点:每个非空树都有且只有一个被称为根的结点。
- 叶子结点:如果结点没有任何子结点,那么此结点称为叶子结点(叶结点)。
- 度:对于一个结点,拥有的子树数(结点有多少分支)称为结点的度(Degree)。
- 深度:从根节点到当前节点
- 高度:从当前节点到叶子节点
二叉树 Binary Tree
二叉搜索树 Binary Search Tree
- 左子树上「所有结点」的值均小于它的根结点的值;
- 右子树上「所有结点」的值均大于它的根结点的值;
- 以此类推,左、右子树也分别为二叉查找树(这就是重复性!)
二、前序遍历
public class Solution {
/**
* @param root: A Tree
* @return: Preorder in ArrayList which contains node values.
*/
public List<Integer> preorderTraversal(TreeNode root) {
// write your code here
List<Integer> result = new ArrayList<>();
if(root == null) {
return result;
}
List<Integer> left = preorderTraversal(root.left);
List<Integer> right = preorderTraversal(root.right);
result.add(root.val);
result.addAll(left);
result.addAll(right);
return result;
}
}
public class Solution {
/**
* @param root: A Tree
* @return: Preorder in ArrayList which contains node values.
*/
public List<Integer> preorderTraversal(TreeNode root) {
// write your code here
List<Integer> result = new ArrayList<>();
if(root == null) {
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
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;
}
}
三、中序遍历
public class Solution {
/**
* @param root: A Tree
* @return: Preorder in ArrayList which contains node values.
*/
public List<Integer> preorderTraversal(TreeNode root) {
// write your code here
List<Integer> result = new ArrayList<>();
if(root == null) {
return result;
}
List<Integer> left = preorderTraversal(root.left);
List<Integer> right = preorderTraversal(root.right);
result.addAll(left);
result.add(root.val);
result.addAll(right);
return result;
}
}
/**
* 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<>();
if (root == null) {
return result;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode current = root;
while (current != null || !stack.isEmpty()) {
while (current != null) {
stack.push(current);
current = current.left;
}
current = stack.pop();
result.add(current.val);
current = current.right;
}
return result;
}
}
四、后序遍历
public class Solution {
/**
* @param root: A Tree
* @return: Preorder in ArrayList which contains node values.
*/
public List<Integer> preorderTraversal(TreeNode root) {
// write your code here
List<Integer> result = new ArrayList<>();
if(root == null) {
return result;
}
List<Integer> left = preorderTraversal(root.left);
List<Integer> right = preorderTraversal(root.right);
result.addAll(left);
result.addAll(right);
result.add(root.val);
return result;
}
}
public class Solution {
/**
* @param root: A Tree
* @return: Postorder in ArrayList which contains node values.
*/
public List<Integer> postorderTraversal(TreeNode root) {
// write your code here
List<Integer> result = new ArrayList<>();
if (root == null) {
return result;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.peek();
if (node.right == null && node.left == null) {
result.add(stack.pop().val);
}
if (node.right != null) {
stack.push(node.right);
node.right = null;
}
if (node.left != null) {
stack.push(node.left);
node.left = null;
}
}
return result;
}
}
public ArrayList<Integer> postorderTraversal(TreeNode root) {
ArrayList<Integer> result = new ArrayList<Integer>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode prev = null; // previously traversed node
TreeNode curr = root;
if (root == null) {
return result;
}
stack.push(root);
while (!stack.empty()) {
curr = stack.peek();
if (prev == null || prev.left == curr || prev.right == curr) { // traverse down the tree
if (curr.left != null) {
stack.push(curr.left);
} else if (curr.right != null) {
stack.push(curr.right);
}
} else if (curr.left == prev) { // traverse up the tree from the left
if (curr.right != null) {
stack.push(curr.right);
}
} else { // traverse up the tree from the right
result.add(curr.val);
stack.pop();
}
prev = curr;
}
return result;
}
五、树序列化
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Codec {
// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if(root == null) {
return "{}";
}
List<TreeNode> list = new ArrayList<>();
list.add(root);
// [1,2,3,null,null,4,5,null,null,null,null]
for (int i = 0; i < list.size(); i++) {
TreeNode node = list.get(i);
if (node == null) {
continue;
}
list.add(node.left);
list.add(node.right);
}
// [1,2,3,null,null,4,5]
while (list.get(list.size() - 1) == null) {
list.remove(list.size() - 1);
}
StringBuilder sb = new StringBuilder("{");
sb.append(list.get(0).val);
// {1,2,3,#,#,4,5}
for (int i = 1; i < list.size(); i++) {
if (list.get(i) == null) {
sb.append(",#");
} else {
sb.append("," + list.get(i).val);
}
}
sb.append("}");
return sb.toString();
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || data.equals("{}")) {
return null;
}
// String[] data 1 2 3 # # 4 5
String[] datas = data.substring(1, data.length() - 1).split(",");
boolean isLeft = true;
List<TreeNode> queue = new ArrayList<>();
TreeNode node = new TreeNode(Integer.parseInt(datas[0]));
queue.add(node);
int index = 0;
for (int i = 1; i < datas.length; i++) {
if (!datas[i].equals("#")) {
TreeNode node1 = new TreeNode(Integer.parseInt(datas[i]));
if (isLeft) {
queue.get(index).left = node1;
} else {
queue.get(index).right = node1;
}
queue.add(node1);
}
if (!isLeft) {
index++;
}
isLeft = !isLeft;
}
return queue.get(0);
}
}
// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(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> result = new ArrayList<>();
if (root == null) {
return result;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
boolean findRight = false;
while (!queue.isEmpty()) {
int size = queue.size();
findRight = false;
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
if (!findRight) {
result.add(node.val);
findRight = true;
}
// 4 5
if (node.right != null) {
queue.offer(node.right);
}
if (node.left != null) {
queue.offer(node.left);
}
}
}
return result;
}
}
七、最近公共祖先
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) {
// write your code here
if(root == null || root == A || root == B) {
return root;
}
TreeNode left = lowestCommonAncestor(root.left, A, B);
TreeNode right = lowestCommonAncestor(root.right, A, B);
if (left != null && right != null) {
return root;
}
if (left != null) {
return left;
}
if (right != null) {
return right;
}
return null;
}
}
八、判断是否平衡二叉树
/**
* 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 boolean isBalanced(TreeNode root) {
// write your code here
if(root == null) {
return true;
}
return maxTree(root) != -1;
}
public int maxTree(TreeNode node) {
if (node == null) {
return 0;
}
int left = maxTree(node.left);
int right = maxTree(node.right);
if (left == -1 || right == -1 || Math.abs(left - right) > 1) {
return -1;
} else {
return Math.max(left, right) + 1;
}
}
}