arrays - 矩阵数组部分的最大和

标签 arrays algorithm matrix time-complexity

我被困在一个简单的问题上,我正在寻找比我的更好的解决方案。

我有一个整数矩阵数组 (tab[N][M]) 和整数 (k),我必须找到最小的矩形(子矩阵数组)它的元素之和大于 k

所以,我目前的解决方案尝试是:

  1. 创建额外的矩阵数组 (sum[N][M]) 和整数 solution = infinity
  2. 对于每个 1 <i <= N + 1 和 1 <j <= M + 1

    sum[ i ][ j ] = sum[ i - 1 ][ j ] + sum [ i ][ j - 1] + tab[ i  ] [ j ] - sum[ i - 1] [ j - 1]  
    
  3. 然后查看从 (x, y) 开始到 (a, b) 结束的每个矩形 f.e

    Rectangle_(x,y)_(a,b) = sum[ a ][ b ] - sum[ a - x ] [ b ] - sum[ a ][ b - y ] + sum[ a - x ][ b - y ]
    

    如果 Rectangle_(x,y)_(a,b) >= k 则 solution = current_solution 和 (a - x) * (b - y) 的最小值

但是这个解决方案很慢(四次时间),有没有可能让它更快?我正在寻找迭代对数时间(或更差/更好)。我设法减少了我的时间,但并没有显着减少。

最佳答案

如果矩阵仅包含 >= 0 的值,则在 1D 情况下存在线性时间解,可以扩展为 2D 情况下的立方时间解。

对于一维情况,您从左到右进行一次传递,在数组上滑动一个窗口,边移动边拉伸(stretch)或收缩它,以便区间中包含的数字总和至少为 k(或突破如果这是不可能的循环)。

最初,将区间的左索引绑定(bind)为第一个元素,右索引绑定(bind)为-1,然后循环:

  • 将右边界递增 1,然后继续递增,直到区间内的值总和 > k,或到达数组末尾。
  • 在不让值之和小于或等于 k ​​的情况下,增加左边界以尽可能缩小间隔。
  • 如果结果是一个有效区间(意味着第一步没有找到有效区间就没有到达数组的末尾)然后将它与目前为止的最小值进行比较,并在必要时进行更新。

如果允许负值,这将不起作用,因为在第二步中,您需要能够假设缩小间隔总是会导致更小的总和,因此当总和低于 k 时,您知道这是可能的最小值对于给定的间隔端点。

对于 2D 情况,您可以遍历所有可能的子矩阵高度,并遍历给定高度的每个可能的起始行,并对每一行执行此水平扫描。

在伪代码中:

假设您有一个函数 rectangle_sum(x, y, a, b),它返回从 (x, y) 到 (a, b) 的值之和,并在 O( 1) 一次使用求和面积表。

for(height = 1; height <= M; height++)  // iterate over submatrix heights
{
    for(row = 0; row <= (M-h); row++)   // iterate over all rows
    {
        start = 0; end = -1; // initialize interval
        while(end < N)  // iterate across the row
        {
            valid_interval = false;
            // increment end until the interval sums to > k:
            while(end < (N-1))
            {
                end = end + 1;
                if(rectangle_sum(start, row, end, row + height) > k)
                {
                    valid_interval = true;
                    break;
                }
            }
            if(!valid_interval)
                break;
            // shrink interval by incrementing start:
            while((start < end) && 
                rectangle_sum(start+1, row, end, row + height) > k))
                start = start + 1;

            compare (start, row), (end, row + height) with current smallest
            submatrix and make it the new current if it is smaller
        }
    }
}

关于arrays - 矩阵数组部分的最大和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41915990/

相关文章:

c++ - 错误 C2719 : '_Val' : formal parameter with __declspec(align ('16' )) won't be aligned?

c - 从 C 中的 typedef 枚举获取数组,索引处的值

java - 获取JAVA中数组中数字之差的总和

Php 包含安全性 - 使用数组和名称前缀

algorithm - 通用最小生成树

r - 在 R 中的矩阵中找到最大值

JAVA 在 JMenuItem[] 构造函数中声明未初始化的 JMenuItem() 项

algorithm - 为什么不总是使用堆排序

algorithm - 概率可调的随机算法

python - Python 语言中的矩阵乘法