LintCode刷题——不同的二叉查找树I、II

不同的二叉查找树I:

题目内容:

给出 n,问由 1...n 为节点组成的不同的二叉查找树有多少种?

样例:

给出n = 3,有5种不同形态的二叉查找树:

1           3    3       2      1
 \         /    /       / \        3      2     1       1   3      2
 /      /       \                  2     1          2                  3

算法分析:

先来看一下二叉查找树的特点,当选定一个节点i作为中间节点时:

  ①位于该节点左子树中的所有节点均小于i,假设该节点的左子树的排列情况有m种;

  ②位于该节点右子树中的所有节点均大于i,假设该节点的右子树的排列情况有n种;

  ③综合①和②,当节点i作为当前二叉查找树的首节点时,该二叉查找树的总排列数目有m*n;

因此对于一个拥有n个节点的二叉查找树,其每一个节点均能成为某一二叉查找树的首节点,因此动态规划的表达式为:

  DP[i] = sum{ DP[j-1] * DP[i-j] },其中1=< j <=i,DP[i]表示i个节点所能组成的二叉查找树的数目;

代码: 

 public int numTrees(int n) {
        // write your code here
        if(n==0)
            return 1;
        int[] result = new int[n+1];
        result[0]=1;
        result[1]=1;
        for(int i=2;i<=n;i++){
            for(int j=1;j<=i;j++){
                int left=result[j-1];
                int right=result[i-j];
                result[i]+=left*right;
            }
        }
        return result[n];
    }

不同的二叉查找树II:

题目内容:

给出n,生成所有由1...n为节点组成的不同的二叉查找树;

样例:

给出n = 3,有5种不同形态的二叉查找树:

1           3    3       2      1
 \         /    /       / \        3      2     1       1   3      2
 /      /       \                  2     1          2                  3

算法分析:

本题在 I 的基础上要求返回的不是组数而是具体的组合,很明显本题需要用递归的方式来解决问题,和 I 的思想基本一致,在递归的过程中找出所有的左右子树的排列组合,然后分别连接到当前节点的左子树和右子树,将结果作为当前层的二叉查找树的所有排列组合进行返回。

代码:

HashMap<String,List<TreeNode>> map = new HashMap<>();
    public List<TreeNode> findSolution(int begin, int end){
        List<TreeNode> result = new ArrayList<>();
        if(begin>end){
            result.add(null);
            return result;
        }
        if(begin==end){
            TreeNode temp = new TreeNode(begin);
            result.add(temp);
            return result;
        }
        String tag = String.valueOf(begin)+"-"+String.valueOf(end);
        if(map.get(tag)!=null){
            return map.get(tag);
        }
        for(int i=begin;i<=end;i++){
            List<TreeNode> left = findSolution(begin,i-1);
            List<TreeNode> right = findSolution(i+1,end);
            if(left.size()!=0&&right.size()!=0){
                for(TreeNode t1:left){
                    for(TreeNode t2:right){
                        TreeNode temp = new TreeNode(i);
                        temp.left = t1;
                        temp.right=t2;
                        result.add(temp);
                    }
                }
            }
            if(left.size()!=0&&right.size()==0){
                for(TreeNode t1:left){
                    TreeNode temp = new TreeNode(i);
                    temp.left = t1;
                    result.add(temp);
                }
            }
            if(left.size()==0&&right.size()!=0){
                for(TreeNode t2:right){
                    TreeNode temp = new TreeNode(i);
                    temp.right = t2;
                    result.add(temp);
                }
            }
        }
        map.put(tag,result);
        return result;
    }
    public List<TreeNode> generateTrees(int n) {
        // write your code here
        map = new HashMap<>();
        return findSolution(1,n);
        /*long startTime=System.nanoTime();
        List<TreeNode> result = findSolution(1,n);
        long endTime=System.nanoTime();
        System.out.println("运行时间为:"+(endTime-startTime));
        return result;*/

    }

代码中我还建立了一个map作为中间结果的记录,用来降低一些重复区间段求解的时间开销,其效果还是很明显的,当n=11时,没有map的算法时间开销为124313992ns,而有map的算法时间开销为82106610ns;但是这题我我试了下即使不用map也能够AC;

时间: 2024-10-23 12:30:18

LintCode刷题——不同的二叉查找树I、II的相关文章

LintCode刷题——打劫房屋I、II、III

打劫房屋I: 题目内容: 假设你是一个专业的窃贼,准备沿着一条街打劫房屋.每个房子都存放着特定金额的钱.你面临的唯一约束条件是:相邻的房子装着相互联系的防盗系统,且 当相邻的两个房子同一天被打劫时,该系统会自动报警.给定一个非负整数列表,表示每个房子中存放的钱, 算一算,如果今晚去打劫,你最多可以得到多少钱 在不触动报警装置的情况下. 样例: 给定 [3, 8, 4], 返回 8. 挑战: O(n) 时间复杂度 且 O(1) 存储. 算法分析: 前提:对于某一间房子i,如果盗贼要打劫该房子,则房

【leetcode刷题笔记】Spiral Matrix II

Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For example,Given n = 3, You should return the following matrix: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 题解:以前做过的Spiral Matrix是给一个矩阵螺旋式的输出,这道题是给一个n,螺旋式的

leetcode 刷题之路 77 Permutations II

Given a collection of numbers that might contain duplicates, return all possible unique permutations. For example, [1,1,2] have the following unique permutations: [1,1,2], [1,2,1], and [2,1,1]. Permutations 的升级版,依旧是全排列问题,但是序列中可能会出现重复数字. 思路:采用字典序的非递归方

【leetcode刷题笔记】Jump Game II

Given an array of non-negative integers, you are initially positioned at the first index of the array. Each element in the array represents your maximum jump length at that position. Your goal is to reach the last index in the minimum number of jumps

【leetcode刷题笔记】Unique Paths II

Follow up for "Unique Paths": Now consider if some obstacles are added to the grids. How many unique paths would there be? An obstacle and empty space is marked as 1 and 0 respectively in the grid. For example, There is one obstacle in the middl

刷题感悟 - Guess Number Game II

最近稍微有点懈怠了 刷题不勤了 勉励下自己 这道题目挺有意思的 We are playing the Guess Game. The game is as follows:I pick a number from 1 to n. You have to guess which number I picked.Every time you guess wrong, I'll tell you whether the number I picked is higher or lower.Howeve

LintCode刷题笔记(九章ladder PartOne)--BugFree

九章ladder的前半部分刷题笔记,在这次二刷的时候补上~ @ 2017.05.21 141 - sqrtx 二分答案 ---  binarySearch二分法 --- class Solution: """ @param x: An integer @return: The sqrt of x """ def sqrt(self, x): # write your code here if not x: return 0 start, end

LintCode刷题笔记-- LongestCommonSquence

题目描述: Given two strings, find the longest common subsequence (LCS). Your code should return the length of LCS. 解题思路: 这一题是非常经典的动态规划问题,在解题思路上可以按照经典的动态规划的解法,这是在系统学习动态规划之后第一个解决的LintCode上的问题: 1.子问题划分 给出两个字符串的A,B,两个字符串长度分别为lenA,lenB,求出两个字符串的LCS: 这划分为子问题:A.

lintcode 容易题:Merge Sorted Array II 合并排序数组 II

题目: 合并排序数组 II 合并两个排序的整数数组A和B变成一个新的数组. 样例 给出A = [1, 2, 3, empty, empty] B = [4,5] 合并之后A将变成[1,2,3,4,5] 注意 你可以假设A具有足够的空间(A数组的大小大于或等于m+n)去添加B中的元素. 解题: 这里给的是两个数组,上题给的是ArrayList格式,比较好处理,重新定义一个长度m+n的数组,太无节操,其他方法一时想不起来 官方解题,方法很技巧,可以倒着排序,这样就很简单了 Java程序: class