【面试算法题总结05】树数据结构

树数据结构:

 

例题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);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值