leetcode第一刷_Unique Paths

从左上到右下,只能向右或向下,问一共有多少种走法。

这个问题当然可以用递归和dp来做,递归的问题是很可能会超时,dp的问题是需要额外空间。

其实没有其他限制条件的话,这个问题有个很简单的解法。给定一个格子,假设是m*n的,从左上角走到右下角的总步数是确定了的,(m+n-2)嘛,即在竖直方向一定要走m-1步,在水平方向一定要走n-1步。那有多少种解法就相当于确定什么时候往下走,什么时候往右走,也即相当于从这m+n-2步中,挑选出m-1步有多少种挑法,因为剩下的肯定要往右走嘛。问题实际上就是求c(m+n-2 , m-1),当然也等于c(m+n-2,n-1),具体用哪一个可以挑个小的好算的。

int getNum(int sum, int part){
    if(part==0||part==sum)
        return 1;
    long long mpart = 1;
    for(int i=2;i<=part;i++)
        mpart *= i;
    long long msum = 1;
    for(int i=sum-part+1;i<=sum;i++)
        msum *= i;
    return (int)(msum/mpart);
}

class Solution {
public:
    int uniquePaths(int m, int n) {
        return getNum(m+n-2, min(m-1, n-1));
    }
};

leetcode第一刷_Unique Paths,布布扣,bubuko.com

时间: 2024-12-28 09:39:58

leetcode第一刷_Unique Paths的相关文章

leetcode第一刷_Unique Paths II

接着上面的问题,如果这个矩阵中有阻塞的障碍,就不能用前面的那种组合数的方法了,因为很多位置实际上是没有路的嘛. 剩下的合理解法只有dp了.跟那个求最小和的非常像,从右下角往前推算,对于一个位置(i, j),它的走法应该是(i+1, j)和(i, j+1)走法的和.对于边界条件还是有一些特殊,最后一行,从右往左,如果是0的话没有问题,等于右侧走法的个数,一旦遇到一个1,那么它以及它左边的走法都必须置成0,你可没有穿墙术. 我觉得题目明确说明了行列的个数,就是在暗示我们可以使用dp的方法,行列个数不

leetcode第一刷_Unique Binary Search Trees

这道题其实跟二叉搜索树没有什么关系,给定n个节点,让你求有多少棵二叉树也是完全一样的做法.思想是什么呢,给定一个节点数x,求f(x),f(x)跟什么有关系呢,当然是跟他的左右子树都有关系,所以可以利用其左右子树的结论,大问题被成功转化成了小问题.最熟悉的方法是递归和dp,这里显然有大量的重复计算,用dp打表好一些. 后来实验的同学说,这其实是一个Catalan数,上网查了一下,果然啊.Catalan数是这样子的: h(0) = 1, h(1) = 1; 递推式:h(n)= h(0)*h(n-1)

leetcode第一刷_Unique Binary Search Trees II

http://acm.hdu.edu.cn/showproblem.php?pid=1507 大致题意:在一个n*m的格子上,黑色的地方不可用,问在白色格子上最多可放多少1*2的矩阵. 思路:建图,每个白色格子与它临近的上下左右的白色格子建边,求最大匹配,答案为最大匹配/2,因为是双向图.最后输出匹配边时,当找到一组匹配边记得将该边标记,以防重复计算. #include <stdio.h> #include <algorithm> #include <set> #inc

leetcode第一刷_Binary Tree Inorder Traversal

递归实现当然太简单,也用不着为了ac走这样的捷径吧..非递归实现还挺有意思的. 树的非递归遍历一定要借助栈,相当于把原来编译器做的事情显式的写出来.对于中序遍历,先要訪问最左下的节点,一定是进入循环后,不断的往左下走,走到不能走为止,这时候,能够从栈中弹出訪问的节点,相当于"左根右"过程的"根",然后应该怎么做呢?想一下中序遍历完根节点之后应该干嘛,对,是走到右子树中继续反复这个过程,可是有一点,假设这个节点不包括右子树怎么办?这样的情况下,下一个应该訪问的节点应该

leetcode第一刷_Sqrt(x)

这道题乍看下来非常简单,实际上要注意的问题非常多. 注意看给出来的函数的接口,返回的是int值,也就是计算结果是个近似值.怎样求呢?难道是从2开始往上算?直到某个值正好接近x?当然不行,肯定超时了.再仔细想一下,对了,有二分法,从最大的开始,每次计算一下平方,如果结果比x大,那么缩短上界,否则提高下界. 思想很正确,下面的问题是最大的那个值是多少?你会毫不犹豫的说出是x啊,x的平方根肯定比x小吧.好,那如果x是INT_MAX呢,你想用什么类型来存储这个平方的结果?而且这样每次减半,也得好一会儿才

leetcode第一刷_Subsets II

要求子集,有非常现成的方法.N个数,子集的个数是2^N,每个元素都有在集合中和不在集合中两种状态,这些状态用[0,pow(2,N)]中每个数来穷举,如果这个数中的第i位为1,说明当前集合中包含源数组中的第i个数. 至于有没有重复的元素,大部分有重复元素的问题,都可以借助一个vis集合,里面存放所有已经求得的集合或者其他形式的解,只有少数题目会超时,哪些问题具体的说. class Solution { public: vector<vector<int> > subsetsWithD

leetcode第一刷_Decode Ways

这道题还挺难的.递归的思路是好想,不过不出意料的超时了. dp嘛.想一下i-1的编码加上第i个编码会怎样,如果加上的这个编码不是0,那么这一位可以独立解码,那长为i的解码个数至少是长为i-1的解码个数.还有呢?如果i-1位是1,可以把i-1位和i位同时解码出来,还有呢?如果i-1位是2而i位是0-6中的数字,也可以同时解码这两位编码.满足这个条件的时候,当前长度的解码个数还要加上i-2时的解码个数. 完全可以用一个数组存放过去的结果,但是很明显,当前的结论只与前一个和前前一个结果有关系.只要用三

leetcode第一刷_Gray Code

说到格雷码,应该没人不知道,具体它有什么用,我还真不是很清楚,我室友应该是专家.生成的规律不是很明显,之前看到帖子讲的,这会儿找找不到了.. 思想是这样的,如果有n位,在第2^(n-1)个编码下面画一条水平线的话,你会发现除了第一位之外,其他位都是关于这条线对称的,如下,以三位格雷码举例: 000 001 011 010 --------------------- 110 111 101 100 很神奇吧,我以前是不知道这个规律的.从一开始的一位格雷码,0,1,开始,每次对称的在上一个前面添加上

leetcode第一刷_Permutation Sequence

这道题还挺好的,如果你的思路是每次生成一个全排列,然后累计到k次,那么停下来吧,肯定超时了亲.. 微软今年的笔试题里有一道类似的,我之前已经提到过了,是只有0和1的字符串,求第k个排列是什么样子的.这道题比那个要难一些,但是总体的思路是一样的.假设有n个数要组成排列,求第k个排列.像填表一样,从高位往地位,逐个填写.先考虑有n-1个数要组成排列,最多有(n-1)!种情况,当第n个数加入后,第n个数可以是从1增加到n的,没增加1,所包含的全排列数就会增加(n-1)!,因此,如果用k/(n-1)!,