casyup.me@outlook.com

0%

leetcode/62ZUnuquePaths

Unique Paths

找到不重复的能到达目标的路径数

my solution (8ms)

典型的可以用递归解决的问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class Solution {
public:
int uniquePaths(int m, int n) {
_m = m;
_n = n;
_cx = 0;

uniquePaths_do(1, 1);

return _cx;
}

private:
void uniquePaths_do(int m, int n) {
if (m == _m && n == _n) {
++_cx;
return;
}

if (m + 1 <= _m)
uniquePaths_do(m + 1, n);
if (n + 1 <= _n)
uniquePaths_do(m, n + 1);
}

int _m;
int _n;
int _cx;
};

结果超时了, 想了一下:

            11
     21            12
  31   22        22   13
41 32 32 23    32 23 23 14

这样子的话, 大多数的迭代都会重复

所以更改了一下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution {
public:
int uniquePaths(int m, int n) {
_m = m;
_n = n;

return uniquePaths_do(1, 1);
}

private:
int uniquePaths_do(int m, int n) {
auto p = make_pair(m, n);

if (road[p] != 0) {
return road[p];
} else if (m == _m && n == _n) {
return 1;
}

int l = 0, r = 0;
if (m + 1 <= _m)
l = uniquePaths_do(m + 1, n);
if (n + 1 <= _n)
r = uniquePaths_do(m, n + 1);

if (road[p] == 0) {
road[p] = l + r;
}

return l + r;
}

int _m;
int _n;
map <pair<int, int>, int> road;
};

通过保存的形式来去掉一些可以重用的计算, 虽然过了, 但是效果不理想

emm… 我没有再从树中能总结出什么好的规律…

the best solution

1
2
3
4
5
6
7
8
9
10
11
12
class Solution {
public:
int uniquePaths(int m, int n) {
vector<vector<int>> path(m, vector<int>(n, 1));
for(int i = m - 2; i >= 0; i--){
for(int j = n - 2; j >= 0; j--){
path[i][j] = path[i + 1][j] + path[i][j + 1];
}
}
return path[0][0];
}
};

简洁又高效, 真是个漂亮的小东西

思路是这样的:

1 1 1
3 2 1

1 1 1
3 2 1
6 3 1

上述分别是 3, 2 和 3, 3 的情况, 假设 rebot 在左下角, star 在右上角(本质上不会有什么改变, 只是换了方向)

从 star 开始往后退, 每一个节点的次数都是他的 上节点次数 + 右节点次数 直到循环结束

最后的左下角就是 rebot 的次数

这样的算法复杂度是 O(n)