我有一个二维数组,随机包含0或1的值。
我如何(最有效地)确定值1(最大行迭代i)和最右边元素(最高列迭代j)的最低元素?
例如:
0 0 1 0
1 0 1 0
0 1 0 0
1 0 0 0
我的程序应该回答 i = 3 (假设第一行是i = 0 )和 j = 2 (首先假设列为0 )。
答案 0 :(得分:3)
这是一个想法:
memrchr
查找每行中的最后一个1
(我假设您将数字存储为char
,而不是{8}}位整数)。1
。这是i
的答案。我们使用缓存友好的一次一行操作来实现这一点,因为C使用行主要顺序。j
的下限(因为您在最后一行找到了1
的最后一个1
。memrchr
从j
的下限开始到每行的末尾。如果您在那里找到任何1
,请更新下限。重复,直到您检查了所有行。1
,你可以立即停止。答案 1 :(得分:1)
使用普通循环,只需从头开始(或结束,根据您想要实现的目标)进行搜索,并检查每个元素。没有更有效的方法。
就C和C ++而言,实现的本质是什么是有效的,什么不是。例如,如果这是一个位字段矩阵,那么在开始搜索各个位之前,首先要将每个字节与0进行比较,然后稍微优化代码。
和往常一样,谈论效率而没有明确其含义是没有意义的。速度?内存消耗?程序大小?在没有给定系统的情况下谈论C或C ++中的有效实现也没有意义。
答案 2 :(得分:1)
这是天真的方法 - 只是遍历数组中的所有位置。最坏情况O(n * m):
#define WIDTH 4
#define HEIGHT 4
int main ()
{
int i,j,col,row;
int arr[HEIGHT][WIDTH] = set_Array();
for (j=0;j<HEIGHT;j++){
for (i = 0; i<WIDTH; i++){
if (arr[j][i]){
row = j>row?j:row;
col = i>col?i:col;
}}}
}
我们如何改善这一点?好吧,我们可以从最后开始并向后工作,但我们必须交替进行行和列,而不是依次访问每个单元格。我们可以查找列,然后排,但效率会降低。
0. 1. 2. 3.
0. 0 0 1 0
1. 1 0 1 0
2. 0 1 0 0
3. 1 0 0 0
在此示例中,我们首先搜索行3
和列3
,然后从搜索中删除它们。然后行2
和列2
最多但不包括已删除的列3
和行3
。然后排1
...
当然,我们会在找到包含1
的最底层的行时停止搜索行,并在找到包含1
的最右边的列时停止搜索列。
代码:
#include <stdio.h>
#define WIDTH 4
#define HEIGHT 4
int main ()
{
int i,j,col = 0, row = 0;
int current_row = HEIGHT;
int current_col = WIDTH;
int arr[WIDTH][HEIGHT] = {{0,0,1,0},{1,0,1,0},{0,1,0,0},{1,0,0,0}};
while (!(row && col))
{
current_row--;
current_col--;
if (!row){
printf("searching row: %d\n",current_row);
for (i = 0; i < current_col; i++){
if (arr[current_row][i]){
row = current_row;
}}}
if (!col){
printf("searching col: %d\n",current_col);
for (j = 0; j < current_row; j++){
if (arr[j][current_col]){
col = current_col;
}}}
}
printf("col: %d, row: %d\n", col, row);
}
输出:
searching row: 3
searching col: 3
searching col: 2
col: 2, row: 3
最坏的情况仍然是O(m * n),实际上稍微差一点(从右下角开始两次测试对角线上的细胞),但平均情况更好。
我们浏览1
的最低未搜索行,然后在最右边的未搜索列中搜索1
。
当您找到最低1
时,您不再搜索每一行以获得更多1
。当您找到最右侧的1
时,您不再搜索每个列以获得更多1
。
这样我们就可以在找到答案后停止搜索,与天真的方法不同,这意味着我们通常不必遍历数组中的每个值。
答案 3 :(得分:0)
如果数组的行大小最多为32个数字,则可以使用单个int32_t
来表示整行:数字的值是整行。
然后你的整个数组将是int32_t
的一维数组:
int32_t matrix[nRows];
现在,您可以通过在O(nRows)时间内找到不等于0的matrix
的最后一个数字来找到最下面的行,并且实现非常简单。
此外,你可以通过以下技巧找到最右边的1:
对于每个matrix[i]
,您通过计算matrix[i] & -matrix[i]
来隔离最右边的1。然后计算此结果的log2将为您提供列数。所有matrix[i]
数字的最大列数可为您提供所需的结果。 (同样是O(nRows)时间,实现非常简单)。
当然,如果行大小超过32个值,则每行必须使用更多int32_t
个值,但原则保持不变。