leetcode题解日练--2016.7.8

日练三题,冰冻三尺非一日之寒。

今日题目:1、唯一的BST数数量;2、将排序数组转换为BST;3、寻找插入位置;4、组合加法III。

今日摘录:那一天我二十一岁,在我一生的黄金时代,我有好多奢望。我想爱,想吃,还想在一瞬间变成天上半明半暗的云,后来我才知道,生活就是个缓慢受锤的过程,人一天天老下去,奢望也一天天消逝,最后变得像挨了锤的牛一样。可是我过二十一岁生日时没有预见到这一点。我觉得自己会永远生猛下去,什么也锤不了我。 ——王小波 《黄金时代》

96. Unique Binary Search Trees | Difficulty: Medium

Given n, how many structurally unique BST’s (binary search trees) that store values 1…n?

For example,
Given n = 3, there are a total of 5 unique BST’s.

1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3
题意:n个节点的二分查找树有多少种组成可能。
思路:
这道题是考察卡特兰数的计算。
n个节点构成的BST,共有多少种情形?
可以这样考虑,根肯定会占用一个结点,那么剩余的n-1个结点可以有如下的分配方式,T(0, n-1),T(1, n-2),…T(n-1, 0),设T(i, j)表示根的左子树含i个结点,右子树含j个结点。
设问题的解为f(n),那么f(n) = f(0)*f(n-1) + f(1)*f(n-2) + …….+ f(n-2)*f(1) + f(n-1)*f(0)。假设f(0) = 1,那么f(1) = 1, f(2) = 2, f(3) = 5。n个节点的组合数就是f(n)。
用DP来解决
代码:

class Solution {
public:
    int numTrees(int n) {
        vector<long>    f(n+1,0);
       f[0] = 1;
       f[1] = 1;
       for(int i=2;i<=n;i++)
        {
            long tmp=0;
            for(int j=0;j<i;j++)
            {
                tmp+=f[j]*f[i-1-j];
            }
            f[i] = tmp;
        }
        return f[n];
    }
};

结果:0ms

2、根据卡特兰数的计算方法,(2n!)/[(n+1)!*(n!)] =(2n!)/[2(n!)*n+1]

class Solution {
public:
    int numTrees(int n) {
        return calcFactorial(2*n)/(calcFactorial(n+1)*calcFactorial(n));    
    }

    int calcFactorial(int m)
    {
        int res = 1;
        for(int i=2;i<=m;i++)
            res*=i;
        return res;
    }
};

结果:Runtime Error
测试样例中n=19的时候无法计算,换成python试一下

class Solution(object):
    def numTrees(self, n):
        """ :type n: int :rtype: int """
        from math import factorial

        return factorial(2*n)/(factorial(n)*factorial(n+1))

结果:40ms

108. Convert Sorted Array to Binary Search Tree | Difficulty: Medium

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

题意:将一个排列好的数组变成一棵 height balanced BST(平衡二分查找树)。
思路:
如何生成一棵平衡的BST?首先可以肯定的一点是完全二叉树一定是平衡的BST。
不妨先看一个完全二叉树的栗子:
leetcode题解日练--2016.7.8_第1张图片
这是一棵满的平衡BST,我们中徐序遍历一次这棵树,看看会出现什么结果。
[1,2,4,5,6,8,9]
根节点是第3个元素(从0开始计数),3=(0+6)/2。左子树的根节点是第1个元素,1=(0+2)/2,右子树的根节点是第5个元素,5=(4+6)/2。
是不是很熟悉,没错,就是在做二分查找,基于这个思路不难写出下面代码。

/** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */
class Solution {
public:
    TreeNode* sortedArrayToBST(vector<int>& nums) {
        if(nums.size()==0)  return NULL;
        TreeNode * root = findRoot(nums,0,nums.size()-1);
        return root;
    }
    TreeNode * findRoot(vector<int>&nums ,int low, int high)
    {
        if(low>high)   return NULL;
        int mid = low+((high-low)>>1);
        TreeNode *root = new TreeNode(nums[mid]);
        root->left = findRoot(nums,low,mid-1);
        root->right = findRoot(nums,mid+1,high);
        return root;
    }
};

结果:16ms

35. Search Insert Position | Difficulty: Medium

Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order.

You may assume no duplicates in the array.

Here are few examples.
[1,3,5,6], 5 → 2
[1,3,5,6], 2 → 1
[1,3,5,6], 7 → 4
[1,3,5,6], 0 → 0

题意:排序数组元素查找问题,如果找到了返回index,找不到就返回其应该插入的位置。
思路:
1、如果在列表中,直接用python的index方法返回index,如果不在,去找第一个比target大的index。

class Solution(object):
    def searchInsert(self, nums, target):
        """ :type nums: List[int] :type target: int :rtype: int """
        if target in nums:
            return nums.index(target)
        else:
            length = len(nums)
            for i in nums:
                if i>target:
                    return nums.index(i)
        return len(nums)

结果:44ms
2、其实问题等价于从一个排序好的数组中去查找第一个大于等于目标数的元素的下标,那么这么想就很简单了,直接用二分查找的方法。

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int low=0,high=nums.size()-1;
        while(low<=high)
        {
            int mid = low+((high-low)>>1);
            if(nums[mid]>=target)   high=mid-1;
            else    low = mid+1;
        }
        return low;
    }

};

结果:8ms

216. Combination Sum III | Difficulty: Medium

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

Example 1:

Input: k = 3, n = 7

Output:

[[1,2,4]]

Example 2:

Input: k = 3, n = 9

Output:

[[1,2,6], [1,3,5], [2,3,4]]

题意:从1-9中挑选k个数,使得其累加和等于整数n,且每个数字只能够用一次。
思路:
Example 2:

Input: k = 3, n = 9

Output:

[[1,2,6], [1,3,5], [2,3,4]]

回溯思想,首先从1开始,尝试1\2\3,发现不行之后弹出3,尝试1\2\4.依次类推。什么时候回溯呢?就是当已经凑够了k个数字,它们的和确不等于n,这个时候显然无法得到我们希望的结果,进行回溯再试下一个末位数。直到最初的第一层递归调用,也就是第一位数字也循环完毕了,说明无更多情况,程序结束。

class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> result;
        vector<int> tmp;
        combination(result,tmp,1,k,n);
        return result;
    }
    void combination(vector<vector<int>> &result,vector<int>tmp,int start,int k,int n)
    {
        if(k==0&&n==0) {  result.push_back(tmp); return; }

        for(int i=start;i<=10-k&&i<=n;i++)
        {
            tmp.push_back(i);
            combination(result,tmp,i+1,k-1,n-i);
            tmp.pop_back();
        }

    }
};

结果:4ms
2、另外一种类似的写法,参照https://discuss.leetcode.com/topic/14641/my-c-solution-backtracking/6

class Solution {
public:
    vector<vector<int>> combinationSum3(int k, int n) {
        vector<vector<int>> result;
        vector<int> tmp;
        combination(result,tmp,k,n);
        return result;
    }
    void combination(vector<vector<int>> &result,vector<int>tmp,int k,int n)
    {
        if(tmp.size()==k&&n==0) {  result.push_back(tmp); return; }
        if(tmp.size()<k)
        {
            for(int i=tmp.empty()? 1:tmp.back()+1;i<10;i++)
            {
                tmp.push_back(i);
                combination(result,tmp,k,n-i);
                tmp.pop_back();
            }
        }
    }
};

结果:4ms

你可能感兴趣的:(LeetCode,编程,生活,日记)