树数据结构:
例题1:把二叉搜索树转换为累加树
让我们逆中序遍历一下
/**
* 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 {
int pre=0;
public TreeNode convertBST(TreeNode root) {
dfs(root);
return root;
}
//这里我们逆中序遍历一下
void dfs(TreeNode root){
if(root==null){
return;
}
dfs(root.right);
root.val+=pre;
pre=root.val;
dfs(root.left);
}
}
例题2:重建二叉树
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
Map<Integer,Integer> map=new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
int n=preorder.length;
for(int i=0;i<n;++i){
map.put(inorder[i],i);
}
return dfs(preorder,inorder,0,n-1,0,n-1);
}
public TreeNode dfs(int[] preorder, int[] inorder,int preorderStart,int preorderEnd,int inorderStart,int inorderEnd){
if(preorderStart>preorderEnd||inorderStart>inorderEnd){
return null;
}
int val=preorder[preorderStart];
TreeNode node =new TreeNode(val);
int index=map.get(val);
node.left=dfs(preorder,inorder,preorderStart+1,preorderStart+index-inorderStart,inorderStart,index-1);
node.right=dfs(preorder,inorder,preorderStart+index-inorderStart+1,preorderEnd,index+1,inorderEnd);
return node;
}
}
例题3:树的子结构
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSubStructure(TreeNode A, TreeNode B) {
if(A==null||B==null){
return false;
}
return isSame(A,B)||isSubStructure(A.left,B)||isSubStructure(A.right,B); //先遍历A
}
public boolean isSame(TreeNode A, TreeNode B){
if(B==null){ //把B遍历完,则为有子结构了
return true;
}
if(A==null||A.val!=B.val){
return false;
}
//如果节点值相同,则在同时遍历A的当前节点和B
return isSame(A.left,B.left)&&isSame(A.right,B.right);
}
}
例题4:二叉树的镜像
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public TreeNode mirrorTree(TreeNode root) {
if(root==null){
return null;
}
TreeNode temp=root.left;
root.left=root.right;
root.right=temp;
mirrorTree(root.left);
mirrorTree(root.right);
return root;
}
}
例题5:对称的二叉树
解法1:递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isSymmetric(TreeNode root) {
return same(root,root);
}
public boolean same(TreeNode root1,TreeNode root2){
if(root1==null&&root2==null){
return true;
}
if(root1==null||root2==null){
return false;
}
if(root1.val!=root2.val){
return false;
}
return same(root1.left,root2.right)&&same(root1.right,root2.left);
}
}
解法2:迭代
队列实现
/**
* 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 isSymmetric(TreeNode root) {
Queue<TreeNode> queue=new LinkedList<>();
queue.offer(root);
queue.offer(root);
while(!queue.isEmpty()){
TreeNode p=queue.poll();
TreeNode q=queue.poll();
if(p==null&&q==null){
continue;
}
if(p==null||q==null||p.val!=q.val){
return false;
}
queue.offer(p.left);
queue.offer(q.right);
queue.offer(p.right);
queue.offer(q.left);
}
return true;
}
}
例题6:二叉搜索树的后序遍历序列
class Solution {
public boolean verifyPostorder(int[] postorder) {
return verify(postorder,0,postorder.length-1);
}
public boolean verify(int[] postorder,int start,int end){
if(start>=end){
return true;
}
int mid=postorder[end];
int i=start;
for(;i<end;++i){
if(postorder[i]>mid){
break;
}
}
int j=i;
for(;j<end;++j){
if(postorder[j]<mid){
return false;
}
}
return verify(postorder,start,i-1)&&verify(postorder,i,end-1);
}
}
例题7:二叉树中和为某一值的路径
/**
* 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 {
List<List<Integer>> result;
List<Integer> temp;
public List<List<Integer>> pathSum(TreeNode root, int target) {
result=new ArrayList<>();
temp=new ArrayList<>();
dfs(root,target);
return result;
}
public void dfs(TreeNode root, int target){
if(root==null){
return;
}
temp.add(root.val);
target-=root.val;
if(root.left==null&&root.right==null&&target==0){
result.add(new ArrayList<>(temp));
}
dfs(root.left,target);
dfs(root.right,target);
temp.remove(temp.size()-1);
}
}
例题8:二叉搜索树与双向链表
/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val,Node _left,Node _right) {
val = _val;
left = _left;
right = _right;
}
};
*/
class Solution {
Node result=null;
Node pre=null;
public Node treeToDoublyList(Node root) {
if(root==null){
return null;
}
dfs(root);
pre.right=result;
result.left=pre;
return result;
}
public void dfs(Node root){
if(root==null){
return;
}
dfs(root.left);
if(pre==null){
result=root;
}else{
pre.right=root;
root.left=pre;
}
pre=root;
dfs(root.right);
}
}
例题9:序列化二叉树
/**
* 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) {
return dfs(root,"");
}
public String dfs(TreeNode root,String result){
if(root==null){
result+="$,";
return result;
}
result+=root.val+",";
result=dfs(root.left,result);
result=dfs(root.right,result);
return result;
}
// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
String[] strs=data.split(",");
List<String> list=new ArrayList<>(Arrays.asList(strs));
return dfs2(list);
}
public TreeNode dfs2(List<String> list){
if(list.get(0).equals("$")){
list.remove(0);
return null;
}
TreeNode root=new TreeNode(Integer.valueOf(list.get(0)));
list.remove(0);
root.left=dfs2(list);
root.right=dfs2(list);
return root;
}
}
例题10:二叉树的中序遍历
解法1:递归
/**
* 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 {
List<Integer> result =new ArrayList<>();
public List<Integer> inorderTraversal(TreeNode root) {
dfs(root);
return result;
}
public void dfs(TreeNode root){
if(root==null){
return;
}
dfs(root.left);
result.add(root.val);
dfs(root.right);
}
}
解法2:迭代
/**
* 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<>();
TreeNode p=root;
while(p!=null||!stack.isEmpty()){
while(p!=null){
stack.push(p);
p=p.left;
}
p=stack.pop();
result.add(p.val);
p=p.right;
}
return result;
}
}
例题11:验证二叉搜索树
解法1:二叉搜索树中序遍历的性质
中序遍历也可以使用迭代方法
/**
* 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 {
List<Integer> arr=new ArrayList<>();
public boolean isValidBST(TreeNode root) {
dfs(root);
for(int i=1;i<arr.size();++i){
if(arr.get(i)<=arr.get(i-1)){
return false;
}
}
return true;
}
public void dfs(TreeNode root){
if(root==null){
return;
}
dfs(root.left);
arr.add(root.val);
dfs(root.right);
}
}
解法2:二叉搜索树的性质
class Solution {
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isValidBST(TreeNode node, long lower, long upper) {
if (node == null) {
return true;
}
if (node.val <= lower || node.val >= upper) {
return false;
}
return isValidBST(node.left, lower, node.val) && isValidBST(node.right, node.val, upper);
}
}
例题12:不同的二叉搜索树
解法1:动态规划
class Solution {
public int numTrees(int n) {
int[] G=new int[n+1];
G[0]=1;
G[1]=1;
for(int i=2;i<=n;++i){
for(int j=1;j<=i;++j){
G[i]=G[i]+G[j-1]*G[i-j];
}
}
return G[n];
}
}
解法2:数学(卡塔兰数 )
背不下来就算了
class Solution {
public int numTrees(int n) {
long result=1;
for(int i=0;i<n;++i){
//不能是result*=2*(2*i+1)/(i+2);
//因为这样2*(2*i+1)/(i+2)会舍去小数部分
result=result*2*(2*i+1)/(i+2);
}
return (int)result;
}
}
例题12:二叉树展开为链表
/**
* 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 {
TreeNode preNode=null;
public void flatten(TreeNode root) {
dfs(root);
return;
}
public void dfs(TreeNode root){
if(root==null){
return;
}
TreeNode leftNode=root.left;
TreeNode rightNode=root.right;
if(preNode!=null){
preNode.right=root;
preNode.left=null;
}
preNode=root;
dfs(leftNode);
dfs(rightNode);
}
}
例题13:二叉树中的最大路径和
/**
* 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 {
int result=Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
getScore(root);
return result;
}
public int getScore(TreeNode root){
if(root==null){
return 0;
}
int maxLeft=Math.max(getScore(root.left),0);
int maxRight=Math.max(getScore(root.right),0);
int newResult=root.val+maxLeft+maxRight;
if(newResult>result){
result=newResult;
}
return root.val+Math.max(maxLeft,maxRight);
}
}