Unique Paths

来源:互联网 发布:短信猫用什么网络 编辑:程序博客网 时间:2024/06/14 15:28

一. Unique Paths

A robot is located at the top-left corner of a m x n grid (marked ‘Start’ in the diagram below).

The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked ‘Finish’ in the diagram below).

How many possible unique paths are there?

这里写图片描述

Above is a 3 x 7 grid. How many possible unique paths are there?

Note: m and n will be at most 100.

Difficulty:Medium

TIME:12MIN

解法一(动态规划)

这道题,按题目说的数据量,如果采用搜索来做,超时肯定超到天边去了。

这道题可以用动态规划来求解:

  • 如果只有一行,那么当然只有一条路可以走,那么可以设定一个数组为[1,1,1,1,1,1,1],表示从该点到终点的所有可能路径数。
  • 如果有两行,我们会发现,第一行的路径数变为了[7,6,5,4,3,2,1],为下面那一行所有可能路径数的叠加值。
  • 同理,如果有三行,那么第一行的路径就是第二行路径的叠加值,而第二行路径为最后一行路径的叠加值。

因此,代码如下:

int uniquePaths(int m, int n) {    vector<int> v(n,1);    while(m > 1) {        for(int i = 1; i < n; i++)            v[i] += v[i - 1];        m--;    }    return v[n - 1];}

代码的时间复杂度为O(mn)

解法二(公式求解)

既然每次向右走和每次向下走的选择都会创造一条独一无二的路径,那么我们可以把行走的路径看出一个排列

比如其中一条路径就可以表示为[D,D,R,R,R,R,R,R],就是一直往下走,到底后就一直往右走。而且,任意两个D和六个R的排列,都是一条独一无二的路径,所以,我们只要求出了两个D和六个R的所有排列数,就相当于求解了3 x 7 grid的所有路径数。

求全排列总数的公式为(m+n)!/(m!n!)

int uniquePaths(int m, int n) {    int big = max(m - 1, n - 1);    int small = min(m - 1, n - 1);    long result = 1;    for(int i = 1, j = big + 1; i <= small; i++, j++) {        result *= j;        result /= i;    }    return (int)result;}

代码的时间复杂度为O(min(n,m))

二. 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 middle of a 3x3 grid as illustrated below.

[
[0,0,0],
[0,1,0],
[0,0,0]
]

The total number of unique paths is 2.

Note: m and n will be at most 100.

Difficulty:Medium

TIME:16MIN

解法(动态规划)

题目改变之后应该是不能用公式来直接求解了,不过还是可以用动态规划来求解。

上面说过是求叠加值,那是因为第一题是第二题的一种特例,其实这道题的最优子结构具体来说可以描述为:

  • dp[i][j] = dp[i+1][j]+dp[i][j+1];

也就是往右边走以及往下走的所有路径之和,而且如果该点为障碍,那么就直接把值设为0即可。

其实这道题自己创建个数组可能会比较简单(就是创建m+1行n+1列的数组),这样处理的边界情况会少很多,不过为了节省空间,我还是使用了输入的数组作为动态规划的数组。

int uniquePathsWithObstacles(vector<vector<int>>& grid) {    int m = grid.size();    int n = grid[0].size();    /*初始化最后一行*/    grid[m - 1][n - 1] = 1 - grid[m - 1][n - 1];    for(int i = n - 2; i >= 0; i--) {        grid[m - 1][i] = grid[m - 1][i] != 1 ? grid[m - 1][i + 1] : 0;    }    for(int i = m - 2; i >= 0; i--) {        /*初始化该行最后一个点*/        grid[i][n - 1] = grid[i][n - 1] != 1 ? grid[i + 1][n - 1] : 0;        for(int j = n - 2; j >= 0; j--) {            //dp过程            grid[i][j] = grid[i][j] != 1 ? (grid[i][j + 1] + grid[i + 1][j]) : 0;        }    }    return grid[0][0];}

代码的时间复杂度为O(mn)

0 0
原创粉丝点击