LeetCode-62 划水记录 04
题目一看;
感觉可以用回溯法 就是从(0.0)开始 走到下一步 再走下一步 走到尽头了 向右边走 到尽头了回去上一个格子 再从上一个格子换一个方向 走 因为只能走2个方向 如果一个格子2个方向都走完了 就又回到上一个
通过这样的办法 可以列出所有路径 并且找到所有的路径数之和。
回溯法递归实现:
代码如下:
//递归版void uniquePaths2(int m, int n,int H,int L,int *res) { if (m == H && n == L) { (*res)++; return 0; } if(m<=H-1) uniquePaths2(m + 1, n,H,L,res); if(n<=L-1) uniquePaths2(m , n+1,H,L,res);}int uniquePaths(int m, int n) { int res = 0; uniquePaths2(1, 1,m,n,&res); return res;}int main(){ int m = 4, n = 4; printf("%d\n", uniquePaths(m, n)); return 0;}
程序跑出来没问题 用题目提供的样本数据 测试都ok
但是再大一点到 m=20 n=15的时候就超时了 随着m n的增加时间几乎也以几何级的速度增长。程序运行几秒cpu就骂人了。。。
然后我想试试迭代版的时间如何
回溯法迭代版:
//迭代版struct Point{ int x, y;};int uniquePaths3(int m,int n){ int x = 0, y = 0,lsx=0,lsy=0; int zt[100][100] = { 0 }; int sum = 0; struct Point Yl[100][100] = { 0 }; while (1) { if (x >= m || y >= n)//该点超出范围了 返回 { lsx = Yl[x][y].x; lsy= Yl[x][y].y; x = lsx; //返回上一点 y = lsy; continue; } switch (zt[x][y]) { case 0://该点未使用过 默认向下 zt[x][y]++; //表明已经向下走了一次 x += 1; Yl[x][y].x = x-1; Yl[x][y].y= y; break; case 1: zt[x][y]++; //表明已经向下走了一次 y += 1; Yl[x][y].x = x ; Yl[x][y].y = y-1; break; case 2: //该点下右都走完了 返回上一点 if (x == 0 && y == 0) { return sum; } zt[x][y] = 0; lsx = Yl[x][y].x; lsy = Yl[x][y].y; x = lsx; //返回上一点 y = lsy; break; default: break; } if (x == m - 1 && y == n - 1 && zt[x][y] == 0) sum++; } return sum;}int main(){ int m = 20, n = 15; printf("%d\n", uniquePaths3(m, n)); //printf("%d\n", uniquePaths(m, n)); return 0;}
结果效果跟递归版一样
。。。然后我就想应该是从0,0 到终点的话会出现很多重复的工作,比如m=10 n=10 从中间5,5到 9,9 点如果有N种走法 那么刚开始 0,0 开始遍历到 5,5的时候 和 1,1遍历到5,5的时候都会从5,5遍历到9,9了。这就重复工作了。可以考虑把5,5到9,9的走法记录下来,然后到5,5的时候就读取这个记录就行了。
但是不能从0,0开始
应该从9,9终点开始向左边走。
然后走到左边终点的时候
就返回到上一层的末尾
如此反复到0,0 这样的话在遍历的过程中每个点都可以获取向下和向右的走法数量 两者之和即为该点到终点的走法数;
代码如下:
#include <stdio.h>/*0 0 0 00 0 0 00 0 0 00 0 0 0*/int uniquePaths2(int m, int n,int h,int l,int **HashMap){ int Sum = 0; if (m<0||n<0)//坐标非法 return 0; if (n >= 0 && n <= l-1)//如果还不用切换到上一行 { if (n >= 0 && n < l-1)//可以向右读 { Sum += HashMap[m][n + 1]; } if (m >= 0 && m < h-1) //可以向下读 { Sum += HashMap[m+1][n]; } if (h-1 == m && l-1 == n) Sum = 1; HashMap[m][n] = Sum; //切换到上一行 if (0 == m && n == 0) { return HashMap[0][0]; } if (n == 0) { return uniquePaths2(m - 1, l-1,h,l,HashMap);//返回到上一行 } else return uniquePaths2(m, n - 1,h,l,HashMap); } return 0;}int uniquePaths(int m, int n) { int xhbl = 0, xhbl2 = 0; //int HashMap[100][100] = { 0 };//记录 leetcode中不能用全局变量 所以只能这样 int **HashMap = malloc(sizeof(int*) * 100); for(xhbl=0;xhbl<100;xhbl++) HashMap[xhbl]=malloc(sizeof(int) * 100); for (xhbl = 0; xhbl < 100; xhbl++) { for (xhbl2 = 0; xhbl2 < 100; xhbl2++) { HashMap[xhbl][xhbl2] = 0; } } HashMap[m-1][n-1] = 1; return uniquePaths2(m - 1, n - 1, m, n,HashMap);}int main(){ printf("%d", uniquePaths(7, 3)); return 0;}
提交到leetcode:
没毛病,就是时间太慢了。。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。