Algorithm之Unique Path

經典排列組合與動態規劃題

[size=medium][b]一、原題:[/b][/size]



// https://leetcode.com/problems/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?


+---+---+---+---+---+---+---+---+
|ROB| | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
| | | | | | | |end|
+---+---+---+---+---+---+---+---+


*/




[size=medium][b]解法一[/b][/size]

/*

// https://discuss.leetcode.com/topic/5623
// java-dp-solution-with-complexity-o-n-m

The assumptions are:

- When (n==0||m==0) the function always returns 1 since the robot
can't go left or up.

- For all other cells. The result = uniquePaths(m-1,n) + uniquePaths(m,n-1)

Therefore I populated the edges with 1 first and use DP to get the full 2-D array.

*/

/*

+----+----+----+----+----+----+----+----+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
+----+----+----+----+----+----+----+----+
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
+----+----+----+----+----+----+----+----+
| 1 | 3 | 6 | 10 | 15 | 21 | 28 | 36 |
+----+----+----+----+----+----+----+----+
| 1 | 4 | 10 | 20 | 35 | 56 | 84 |120 |
+----+----+----+----+----+----+----+----+

*/


// Time complexity: O(n^2)

public int uniquePaths(int m, int n) {
int[][] map = new int[m][n];

for(int i = 0; i < m; i++){
map[i][0] = 1;
}

for(int j = 0; j < n; j++){
map[0][j] = 1;
}

for(int i = 1; i < m; i++){
for(int j = 1; j < n; j++){
map[i][j] = map[i-1][j] + map[i][j-1];
}
}

return map[m-1][n-1]; // the finish star.
}


[size=medium][b]解法二[/b][/size]

// Time complexity: O(n^2)

public int uniquePaths(int m, int n) {
int[]dp = new int[n];
dp[0] = 1;
for(int i = 0; i < m; i++)
for(int j = 1; j < n; j++)
dp[j] = dp[j] + dp[j-1];
return dp[n-1]; // the finish star.
}



[size=medium][b]解法三[/b][/size]

// Time complexity: O(n)
/*
https://discuss.leetcode.com/topic/52660
// java-0ms-solution-with-explanations


When we solve this problem, we should keep in mind that this is a
permutation and combination problem of high school level.
Therefore, we need not to use DP solution or recursive solution.

Given m and n, there will be m+n-2 steps.
Among these m+n-2 steps, n-1 steps are towards right and m-1 steps are towards down.

the question is changed to: Select m-1 steps from m+n-2 steps.
So, there will be (m-1)C(m+n-2) solutions, which is the same as (n-1)C(m+n-2).

All we need is to write a program quickly calculating (m-1)C(m+n-2) or (n-1)C(m+n-2).
*/

public int uniquePaths(int m, int n) {
long result = 1;
int steps = m + n - 2;

for(int i=0; i < Math.min(m-1,n-1); i++)
result = result * (steps - i) / (i + 1);

return (int)result;
}


/*
注意:

result = result * (steps - i) / (i + 1);

不要寫成

result *= (steps - i) / (i + 1);

的形式,否則後者在做除法時丟位導致結果錯誤。


*/




[size=medium][b]解法四[/b][/size]


// Time complexity: O(n)
/*

https://discuss.leetcode.com/topic/52660
// java-0ms-solution-with-explanations

https://discuss.leetcode.com/topic/31724
// java-solution-0ms-4lines


When we solve this problem, we should keep in mind that this is a
permutation and combination problem of high school level.
Therefore, we need not to use DP solution or recursive solution.

Given m and n, there will be m+n-2 steps.
Among these m+n-2 steps, n-1 steps are towards right and m-1 steps are towards down.

the question is converted to: Select m-1 steps from m+n-2 steps.
So, there will be (m-1)C(m+n-2) solutions, which is the same as (n-1)C(m+n-2).

All we need is to write a program quickly calculating (m-1)C(m+n-2) or (n-1)C(m+n-2).



*/

/*

基礎知識:(從 n 個數中 取出 m 個數)

排列公式: result = n!/(n-m)!
組合公式: result = n!/(n-m)!/m!

------------------------------------------------------

該題是一個組合題:

7, 3

steps = 8

n = 3

result = 8!/(3!*(8-3)!)

8 7 6 5 4 3 2
- - - * - - - -
3 2 1 5 4 3 2


*/
public int uniquePaths(int m, int n) {
int steps = m + n - 2;
int min = Math.min(m - 1, n - 1);

long sum = 1, sub = 1;
for(int i = 0; i < min; i++){
sum *= (steps - i);
sub *= (min - i);
}

return (int)(sum/sub);
}

/*
注意:這種解法乘完再除,相乘的結果可能會造成溢位,而出錯。
所以只適合數比較小的情況。

*/





[size=medium][b]二、增加些難度[/b][/size]

/*
https://leetcode.com/problems/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.
*/


public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int width = obstacleGrid[0].length;
int[] dp = new int[width];
dp[0] = 1;
for (int[] row : obstacleGrid) {
for (int j = 0; j < width; j++) {
if (row[j] == 1)
dp[j] = 0;
else if (j > 0)
dp[j] += dp[j - 1];
}
}
return dp[width - 1];
}




-
發佈了279 篇原創文章 · 獲贊 4 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章