[英]2D array: Sum of elements of a subsquare of the 2d array
给定一个2D数组,我可以毫不费力地将所有元素添加到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];
}
}
我相信从一个[0] [0]开始,它总计一个3x3的单元格。 我迷失了如何从这里获得所有其他3x3细胞组合并比较它们以找到最低的3x3细胞值。 如果我可以使用下一个3x3单元格,我知道我可以使用某种比较语句,并将sum变量更改为下一个总和(如果它更低)。
我怎么能做到这一点? 我是否需要在for循环中添加更多图层?
让我们从定义开始:
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
你所写的代码,两个for循环停止在3,可以计算你想要的3x3子矩阵中从[0] [0]开始的数字,正如你所说的那样。 你现在需要做的是:
确定您拥有的所有起点,确保其中包含3行和3列,包括您所在的元素,并根据每个可能的起点调用该函数,并且
扩展该代码,使其可以从矩阵中的任何点开始。
以下是我们如何进行第1点:
你有一个4x4矩阵,但我们可以很容易地将它推广到NxM矩阵。 N表示有N行,即每列有N个元素。 所以让我们考虑一个专栏。 如果你有N个元素,你可以找到3个连续元素的组? 注意,它不是N-3(看起来像一个明显的答案,但它是错的):
所以一般来说你有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;
}
应该这样做。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.