我有一个包含正整数值的4乘n矩阵。我想从每一行中选择一个值,以便我们将M_ {1,j_1},M_ {2,j_2},M_ {3,j_4},M_ {4,j_4}作为输出主题如下:
这是否有快速算法?
答案 0 :(得分:2)
让我们从仅有2行的简单情况开始:按顺序递增j_2并检查每个M_ {2,j_2},同时跟踪最佳M_ {1,j_1}值(最大M_ {1,j_1}对于j_1 获得最佳M_ {1,j_1}值的一种显而易见的方法是保持(不断增长)二进制搜索树的M_ {1,1}的值.M_ {1,j_2-1}第一个前缀行,并在此树中查找M_ {2,j_2}值的前导。但这会导致次优O(n log n)算法。 对于O(n)时间复杂度,我们需要一个更简单的数据结构:堆栈。在将第一行的某些元素添加到堆栈之前,从堆栈中弹出小于或等于当前元素的所有内容(这会使堆栈保持强烈递减的顺序)。当搜索M_ {2,j_2}值的前导时,也从堆栈中弹出小于或等于M_ {2,j_2}的所有内容,除了最后一个这样的值,并将其用作最佳M_ {1,j_1}值。 要添加第三行,只需将2行方法应用于前2行和第3行的最大值。要添加第四行,请再次应用相同的算法。 整个算法将扫描矩阵3次,同时它将元素向/从堆栈推送和弹出最多3 * n次,因此其时间复杂度为O(n)。如果我们在运行中计算前缀最大值,则可以消除存储2个中间阵列所需的额外O(n)空间。但是我们仍然需要O(n)空间用于堆栈。如果允许破坏输入矩阵的内容,可以用O(1)额外空间来解决问题:只需重用3行3个堆栈或1个堆栈+ 2个中间数组(尽管如果你实现它会非常棘手)需要报告最佳值的指数。)
答案 1 :(得分:1)
我认为你不能在接近2行的线性时间内解决它,所以这样做4似乎不太可能。
我认为最好的方法是动态编程:对于每个连续的行(2..4),找到你可以为该行的每个元素计算的最佳总和(以及产生它的元素,如果需要的话) ,假设您已经计算了较低行的最佳总和;然后在第4行中使用最好的总和。