【问题标题】:2D array: Sum of elements of a subsquare of the 2d array二维数组:二维数组的子正方形的元素之和
【发布时间】:2015-02-14 00:13:04
【问题描述】:

给定一个二维数组,我可以毫不费力地将其所有元素添加到 sum 变量中。说一个 4x4 数组:

1 2 3 4

1 2 2 3

1 2 2 2

1 1 3 3

我对所有元素求和的代码是执行一个 for 循环:

for (i = 0; i < rows; i++)
{
 for (j = 0; j < columns; j++)
 {
   sum += somearray[i][j];
 }
}  

假设所有变量都已正确声明,我相信这是正确的。但是,我在对同一个数组中的 3x3 单元格求和时遇到了麻烦。我想找到总和最低的 3x3 单元格。

for (i = 0; i < 3; i++)
{
 for (j = 0; j < 3; j+++
 {
   sum += somearray[i][j];
 }
}

我相信这是从 somearray[0][0] 开始的 3x3 单元格的总和。我不知道如何从这里获取所有其他 3x3 单元格组合并比较它们以找到最低的 3x3 单元格值。如果我可以下一个 3x3 单元格,我知道我可以使用某种比较语句并将 sum 变量更改为下一个 sum(如果它较低)。

我怎样才能做到这一点?我需要在我的 for 循环中添加更多层吗?

【问题讨论】:

    标签: c++ arrays comparison 2d


    【解决方案1】:

    让我们从定义开始:

    size_t rows; // number of rows
    size_t columns; // number of columns
    int array[rows][columns];
    

    辅助函数:

    int sum(size_t row, size_t column)
    {
       int res = 0;
    
       if (row > rows - 3 || column > columns - 3)
       {
          abort(); // we can out of index operations here...
       }
    
       for (size_t i = 0; i < 3; ++i)
       {
           for (size_t j = 0; j < 3; ++j)
           {
               res += array[i + row][j + column];
           }
       }
       return res;
    }
    

    现在我们可以开始了……

    int min_value = INT_MAX;  // Just the maximum we can imaging
    size_t min_row = 0, min_column = 0; // whatever
    
    for (size_t i = 0; i <= rows - 3; ++i)
    {
       for (size_t j = 0; j <= columns - 3; ++j)
       {
          int value = sum(i, j);
          if (value < min_value)
          {
             min_value = value;
             min_row = i;
             min_column = j;
          }
       }
    }
    ... // done - here min_value is the minimum sum,
        // and min_row, min_column are indexes of the 3x3 entry
    

    【讨论】:

    • 回复上的求和函数,你还是要传递数组吧?我还收到了 min_row、min_column 未使用的变量警告。现在调试
    【解决方案2】:

    正如您所说,您编写的代码(两个 for 循环都停止在 3)使您可以在从 [0][0] 开始的 3x3 子矩阵中计算您想要的数字。你现在需要做的是:

    1. 确定您拥有的所有起点,确保 从那里开始有 3 行 3 列,包括 您所在的元素,并在每个可能的情况下调用该函数 起点和

    2. 扩展该代码,使其可以从 矩阵。

    下面是我们如何继续第 1 点:

    您有一个 4x4 矩阵,但我们可以轻松地将其推广到 NxM 矩阵。 N表示有N行,即每列有N个元素。所以让我们考虑一个列。如果你有 N 个元素,你能找到多少组 3 个连续的元素?当心,它不是 N-3(这看起来是一个显而易见的答案,但它是错误的):

    • N=3 个元素只有 1 个(如果有 123 个,则该组为 123 个)
    • N=4 个元素有 2 个(如果有 1234 个,则组为 123 和 234)
    • N=5 个元素有 3 个(如果有 12345,则组为 123, 234, 345)

    所以一般来说你有 N - 3 + 1 个组(当然你可以认为它是 N-2,但我更喜欢用 3 来表示,因为这是我们每次取的元素数量)。

    同样的方法可以应用于列:如果它们是 M,你可以采取 M - 3 + 1 个组。

    也就是说,您可以在 NxM 矩阵中找到多少个 3x3 子矩阵?首先,您可以找到所有 3 的“垂直”组,即 N-3+1。对于他们每个人,你能组成多少个 3 人的“水平”组? M-3+1。那么你总共有 (N-3+1)*(M-3+1) 个 3x3 子矩阵。这是检查每个子矩阵必须进行的迭代次数。这些 N-3+1 个元素中的每一个都是一行(我们正在垂直移动,即沿着一列,所以这些是行),所以这是一个我们可以开始检查矩阵的元素 - 只要我们有足够的水平空间,即有足够的列。对于这些行中的每一行,我们必须检查 M-3+1 列(沿行水平移动),其中可以开始一个 3x3 子矩阵。

    int min_found = 0; // So far we haven't found a minimum yet
    int min_value, min_row, min_column;
    int max_rows    = (N-3+1);
    int max_columns = (M-3+1);
    
    for (int start_row = 0; start_row < max_rows; start_row++) {
        for (int start_column = 0; start_column < max_columns; start_column++) {
            int current_sum = calculate_sum_of_submatrix(start_row, start_column);
            if ( (min_found == 0) || (min_found == 1 && current_sum < min_value) ) 
                min_value = current_sum;
                min_row    = start_row;
                min_column = start_column;
                min_found = 1;
            }
        }
    }
    
    cout << "The 3x3 submatrix whose elements have the minimum sum "
         << "starts at row " << min_row << " and column " << min_column
         << ", and the sum is " << min_sum << endl;
    

    在您的情况下(N=4,M=4),我们需要检查 N-3+1=2 行和 M-3+1=2 列。所以我们从 [0][0] 开始,然后内部循环将我们带到 [0][1],然后内部循环将结束,我们将继续到外部循环,这将带我们到第 1 行,内部循环将检查 [1][0] 和 [1][1]。然后就结束了。到这个时候,我们将检查所有 4 个 3x3 子矩阵,并且我们会知道最小值。

    现在,第 2 点:我们必须调整您已经拥有的功能,以便从我们想要的位置开始,而不是总是从 [0][0] 开始。这很容易,我们只需在由起始位置(在您的代码中始终为 [0][0])和您已经拥有的 [i][j] 索引的总和给出的位置读取矩阵.像这样:

    int calculate_sum_of_submatrix(int start_row, int start_column) {
        int sum = 0;
        for (int i = 0; i < 3; i++) {     // I would replace i with "submatrix_row"
            for (int j = 0; j < 3; j++) { // I would replace j with "submatrix_column"
                sum += somearray[start_row + i][start_column + j];
            }
        }
        return sum;
    }
    

    应该可以的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 2011-07-28
      • 2015-10-10
      • 1970-01-01
      • 2020-03-09
      • 1970-01-01
      相关资源
      最近更新 更多