Java-通过2D数组的路径中的最大和
基本上我有一个类似的问题: 有一个草莓植物园,由二维方形阵列表示。每种植物(每种元素)都有许多草莓。从阵列的左上角开始,只能向右或向下移动。我需要设计一个递归方法来计算穿过花园的路径,然后输出哪条路径的草莓产量最高 我想我已经理解了非常简单的递归问题,但是这个问题已经超出了我的理解范围。就创建递归方法而言,我不确定从何处开始,也不确定从何处着手 非常感谢与代码相关的任何帮助或帮助我理解此问题背后的概念。谢谢。您可以使用。这里是类似Java的伪文档(Java-通过2D数组的路径中的最大和,java,arrays,path,2d,sum,Java,Arrays,Path,2d,Sum,基本上我有一个类似的问题: 有一个草莓植物园,由二维方形阵列表示。每种植物(每种元素)都有许多草莓。从阵列的左上角开始,只能向右或向下移动。我需要设计一个递归方法来计算穿过花园的路径,然后输出哪条路径的草莓产量最高 我想我已经理解了非常简单的递归问题,但是这个问题已经超出了我的理解范围。就创建递归方法而言,我不确定从何处开始,也不确定从何处着手 非常感谢与代码相关的任何帮助或帮助我理解此问题背后的概念。谢谢。您可以使用。这里是类似Java的伪文档(memo、R和C被假定为max方法可用的实例变量
memo
、R
和C
被假定为max
方法可用的实例变量)
正如dasblinkenlight所说,实现这一点最有效的方法是使用记忆或动态编程技术。我倾向于选择动态编程,但这里我将使用纯递归 答案围绕着一个基本问题的答案:“如果我在我的领域的r行和c列的正方形中,我如何评估从左上角到这里的路径,从而使草莓的数量最大化?” 实现这一点的关键是,只有两种方法可以进入r行和c列中的绘图:要么我可以从上面进入,使用r-1行和c列中的绘图;要么我可以从侧面进入,使用r行和c-1列中的绘图。之后,您只需确保了解基本情况……这意味着,从根本上说,我的纯递归版本类似于:
int[][] field;
int max(int r, int c) {
//Base case
if (r == 0 && c == 0) {
return field[r][c];
}
//Assuming a positive number of strawberries in each plot, otherwise this needs
//to be negative infinity
int maxTop = -1, maxLeft = -1;
//We can't come from the top if we're in the top row
if (r != 0) {
maxTop = field[r-1][c];
}
//Similarly, we can't come from the left if we're in the left column
if (c != 0) {
maxLeft = field[r][c-1];
}
//Take whichever gives you more and return..
return Math.max(maxTop, maxLeft) + field[r][c];
}
打电话给max(r-1,c-1)获取您的答案。注意这里有很多低效的地方;通过使用动态编程(我将在下面提供)或备忘录(已经定义),您会做得更好。但是要记住的是,DP和记忆技术都是更有效的方法,它们来自于这里使用的递归原则
DP:
int-maxValue(int[][]字段){
int r=字段长度;
int c=字段[0]。长度;
int[]maxValues=新的int[r][c];
对于(int i=0;i
在这两种情况下,如果要重新创建实际路径,只需保留一个与“我是从上面来的还是从左边来的”对应的布尔值的2D表格即可?如果大多数草莓路径来自上面,则将其置为真,否则置为假。这可以使您在计算后回溯面片
请注意,这在原则上仍然是递归的:在每一步中,我们都会回顾以前的结果。我们只是碰巧缓存了我们以前的结果,这样我们就不会浪费大量的工作,我们以智能的顺序攻击子问题,这样我们就可以始终解决它们。有关动态规划的更多信息,请参见。您可以使用DP制表方法解决此问题,使用此方法可以将空间从O(m*n)节省到O(n)。使用DP记忆,您需要m*n矩阵来存储中间值。下面是我的Python代码。希望能有所帮助
def max_path(field):
dp = [sum(field[0][:i]) for i in range(1, len(field[0]) + 1)]
for i in range(1, len(field)):
for j in range(len(dp)):
dp[j] = min(dp[j], dp[j - 1] if j > 0 else float('inf')) + field[i][j]
return dp[-1]
它必须是递归的吗?这里的迭代会更简单。是的,它必须是递归的。好吧,dasblinkenlight的答案很好,你只需要跟踪向下或向右是否会产生更大的数字。你可能是指
返回最大值[r-1][c-1]嗨,DivineWolfwood,你的例子很有趣。但是,我想左右看的是什么?你是说你每走一步都可以向左、向右或向下走?这是一个完全不同的问题,因为它允许你在不同的地方重复步骤。我必须仔细考虑一个算法。动态规划方法非常有效,谢谢!嘿@DivineWolfwood我需要类似问题的帮助。如果必须从左下角开始,并且只能根据数组中存在的最高值移动到顶部或右侧,您将如何选择遍历2D数组。嘿,您能帮我做同样的事情吗,但有一个问题。
int maxValue(int[][] field) {
int r = field.length;
int c = field[0].length;
int[][] maxValues = new int[r][c];
for (int i = 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (i == 0 && j == 0) {
maxValues[i][j] = field[i][j];
} else if (i == 0) {
maxValues[i][j] = maxValues[i][j-1] + field[i][j];
} else if (j == 0) {
maxValues[i][j] = maxValues[i-1][j] + field[i][j];
} else {
maxValues[i][j] = Math.max(maxValues[i][j-1], maxValues[i-1][j]) + field[i][j];
}
}
}
return maxValues[r-1][c-1];
}
def max_path(field):
dp = [sum(field[0][:i]) for i in range(1, len(field[0]) + 1)]
for i in range(1, len(field)):
for j in range(len(dp)):
dp[j] = min(dp[j], dp[j - 1] if j > 0 else float('inf')) + field[i][j]
return dp[-1]