给出一个带有权重的2D数组,找到2D数组的最大和,条件是我们只能从一行中选择一个元素,并且不能选择所选元素下的元素(此条件应对所有元素都成立被选中)。我们还可以看到sum包含的元素等于行数。
如果arr [i] [j]是任何选定的元素,那么我无法选择arr [i + 1] [j]。同样,从每一行中只能选择一个元素。例如,如果选择arr [i] [1],则无法选择arr [i] [2或3或..]
编辑-我尝试使用DP解决它。 拿了一个二维数组DP DP [i] [j] = max(arr [i + 1] [k],其中k = 1到n,k!= j)+ arr [i] [j] 然后执行此操作以构建DP矩阵,最后循环计算最大值。 但是我认为当我这样处理时,复杂度很高。请帮忙!
输入矩阵-
1 2 3 4
5 6 7 8
9 1 4 2
6 3 5 7
输出- 27
答案 0 :(得分:2)
class Solution {
private static int maximumSum(int[][] mat){
int rows = mat.length;
int cols = mat[0].length;
int[] ans = new int[cols];
int[] index = new int[cols];
int max_val = 0;
for(int i=0;i<cols;++i){
ans[i] = mat[0][i];
index[i] = i;
max_val = Math.max(max_val,ans[i]); // needed for 1 row input
}
for(int i=1;i<rows;++i){
int[] temp = new int[cols];
for(int j=0;j<cols;++j){
temp[j] = ans[j];
int max_row_index = -1;
for(int k=0;k<cols;++k){
if(k == index[j]) continue;
if(max_row_index == -1 || mat[i][k] > mat[i][max_row_index]){
max_row_index = k;
}
}
temp[j] += mat[i][max_row_index];
index[j] = max_row_index;
max_val = Math.max(max_val,temp[j]);
}
ans = temp;
}
return max_val;
}
public static void main(String[] args) {
int[][] arr = {
{1,2,3,4},
{5,6,7,8},
{9,1,4,2},
{6,3,5,7}
};
System.out.println(maximumSum(arr));
}
}
输出:
27
算法:
在这里让我们采用自上而下的方法。我们从头到尾地将行保持在ans
数组中。
让我们通过示例进行锻炼。
案例:
{1,2,3,4},
{5,6,7,8},
{9,1,4,2},
{6,3,5,7}
[1,2,3,4]
。[5,6,7,8]
,1
,2
,3
遍历4
,跳过每个索引的列下方。例如,对于1
,我们跳过下面的5
,并在所有列中取最大值,然后将其添加到1
中。其他元素也一样。
因此,现在ans
数组看起来像[9, 10, 11, 11]
。 [9, 10, 11, 11]
和下一行[9,1,4,2]
进行锻炼,依此类推。为此,我们得到[13, 19, 20, 20]
,对于最后一行[6,3,5,7]
,我们得到[20, 26, 27, 26]
,其中27
是最高值和最终答案。m
是列。更新#1:
通过维护,您可以将复杂度从 O(n 3 )降低到 O(n 2 )每行2个最大索引。这将始终有效,因为即使1个最大的索引与j
的当前索引temp[j]
相同,另一个最大索引也将始终提供最大值。感谢 @MBo 的建议。我留给读者练习。
更新#2:
我们还需要维护在最后一行中选择了哪个元素的索引。 请记住这一点,因为我们可以准确地判断当前行的路径。