【发布时间】:2017-01-07 02:34:09
【问题描述】:
问题
给定一个由非负数填充的 m x n 网格,找到一条从左上角到右下角的路径,最大化沿其路径的所有数字的总和。
注意:您只能在任何时间点向下或向右移动。
接近
我刚刚用天真的递归处理了这个问题,我为此编写的代码如下所示。 我遇到的问题是我无法弄清楚如何恢复网格中的路径。我通过引用(路径)传入了一个向量,因此我可以恢复每个递归调用的路径。
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int getMaxPath(vector<vector<int> > Grid, int r, int c, vector<int> &path)
{
if((r > Grid.size()-1) || (c > Grid[0].size()-1))
return 0;
if(r==Grid.size()-1 && c==Grid[0].size()-1){
return Grid[r][c];
}
int rs = getMaxPath(Grid, r, c+1, path);
int ds = getMaxPath(Grid, r+1, c, path);
return max(rs,ds)+Grid[r][c];
}
int maxPath(vector<vector<int> > Grid, vector<int> &path)
{
return getMaxPath(Grid, 0, 0, path);
}
int main() {
vector<vector<int> > mat{{5,0,8,12}, {11,16,9,13},{10,2,15,300},{3,14,18,19}};
vector<int>path;
path.push_back(mat[0][0]);
int result = maxPath(mat, path);
cout << result << endl;
for(auto i : path)
cout << i << " " << endl;
return 0;
}
正如我们所看到的,代码的主要部分是递归,我会这样恢复路径(注释)--
int getMaxPath(vector<vector<int> > Grid, int r, int c, vector<int> &path)
{
if((r > Grid.size()-1) || (c > Grid[0].size()-1))
return 0;
if(r==Grid.size()-1 && c==Grid[0].size()-1){
return Grid[r][c];
}
int rs = getMaxPath(Grid, r, c+1, path);
int ds = getMaxPath(Grid, r+1, c, path);
(rs > ds) ? path.push_back(Grid[r][c+1]) ? path.push_back(Grid[r+1][c]); // Recover path here.
return max(rs,ds)+Grid[r][c];
}
但我在某处遗漏了要点,因为这会导致当前元素的多个副本在从递归调用中展开和展开时进入路径。
我做错了什么?
【问题讨论】:
-
如果你在一次采访中给了我这个答案,我会问你这个函数需要多长时间,以及完成这项工作的函数应该需要多长时间。跨度>
-
有很多更好的方法来解决这个问题:你考虑过动态规划吗?
-
@MattTimmermans 这个函数是时间指数的 (2^(r+c))...当然可以使用 DP [?] 将时间减少到 O(m*n) 但是这个想法是为了获得正确的逻辑来恢复路径。
-
没错。当您提出 O(n*m) 算法时,路径将更容易恢复。
-
其实不用恢复。只需确定正确的路径还是下行路径是更好的选择。根本不需要递归。
标签: c++ algorithm recursion matrix