如何使用C在2D数组中查找连续元素

时间:2014-05-07 15:12:55

标签: c arrays

我有一个land=0water=1的2D数组。我已经制定了一个逻辑来获得最大可用范围,即2D阵列中可用的最大连续着陆位。然而,当我在纸上使用这种逻辑时,它给出了正确的答案,但在系统上却没有给出正确的答案。

假设数组Array[3][9]有元素:

0 1 1 0 1 0 0 0 1   
0 1 0 1 0 0 0 0 0   
1 1 1 1 1 0 0 1 1  

在下面的代码中,数组是input2。

输出应为10。

我开发的逻辑是

int countContigious(char* array[],int x,int y,int row1,int col1)
{
if(x<0||x>=row1||y<0||y>=col1||array[x][y]!=0)
{
    return 0;
}
else
{
    array[x][y]=2;
    return 1+countContigious(array,x-1,y,row1,col1)+countContigious(array,x+1,y,row1,col1)+countContigious(array,x,y-1,row1,col1)+countContigious(array,x,y+1,row1,col1);
}
} 
int largestSize(int input1[],char* input2[])
{
int row,col,i,j;
int count=0;
int result=0;
row=input1[0];
col=input1[1];
for(i=0;i<row;i++)
{
    for(j=0;j<col;j++)
    {
        if(input2[i][j]==0)
        {
            count=countContigious(input2,i,j,row,col);
            if(count>result)
            {
                result=count;
            }
        }
    }
}
return result;
}

据我说它应该在变量结果中返回答案。任何人都能说出我的逻辑中有什么问题吗?

2 个答案:

答案 0 :(得分:0)

你有一个2D数组。遍历它的常用方法是循环加倍。 通常的顺序是这样的: 第1行 - 第1列 第1行 - 第2列 .. 第1行 - 最后一列 第2行 - 第1列 ... 最后一行 - 最后一栏

假设您使用上述订单,您可能希望执行以下操作:

每当你找到一个土地位时,探索该位置的右侧,上部,右上部,右下部和底部的阵列(在此步骤之前访问其他方向)并找到最大长度contigius zeros。

这是一个非常天真的例子:

#include <stdio.h>

int main() {
  const int N = 4;
  const int M = 5;

  int a[4][5] =
  {
    { 1, 0, 0, 0, 0},
    { 0, 0, 1, 1, 0},
    { 0, 1, 0, 0, 0},
    { 0, 0, 0, 0, 0}
  };

  /* A naive implementation, which can optimized.
   * Some initializations are not needed.
   */

  int i, j, k, z, len;
  int max_len = -1;

  // traverse the array in the order described before
  for(i = 0 ; i < N ; ++i)
  {
    for(j = 0 ; j < M ; ++j)
    {
      /* Land bit found! Explore the array in the needed directions. */
      if(a[i][j] == 0) {

        // remember where we start from
        k = i;
        z = j;
        len = 0;
        // search right
        // while we are inside the limits of the array
        // (here we need to check only the columns, since
        // we move to the right)
        while(z < M) {
          // and we find land bits
          if(a[k][z++] == 0)
            len++; // increase the current length
          else     // we want contiguous land bits
            break; // we found a water bit, so break this loop
        }

        // is the current length better than the current found?
        if(len > max_len)
          max_len = len; // yes, so update max_len


        // return back to initial cell we started from
        k = i;
        z = j;
        len = 0;
        // search down
        while(k < N) {
          if(a[k++][z] == 0)
            len++;
          else
            break;
        }
        if(len > max_len)
          max_len = len;

        k = i;
        z = j;
        len = 0;
        // search right and down
        while(k < N && z < M) {
          if(a[k++][z++] == 0)
            len++;
          else
            break;
        }
        if(len > max_len)
          max_len = len;

        k = i;
        z = j;
        len = 0;
        // search upper
        while(k >= 0) {
          if(a[k--][z] == 0)
            len++;
          else
            break;
        }
        if(len > max_len)
          max_len = len;

        k = i;
        z = j;
        len = 0;
        // search upper and right
        while(k >= 0 && z < M) {
          if(a[k++][z++] == 0)
            len++;
          else
            break;
        }
        if(len > max_len)
          max_len = len;
      }
    }
  }

  printf("max_length = %d\n", max_len);

  return 0;
}

在理解了天真的方法之后,试着看看你的方法错过了什么。使用纸张并尝试使用较小的示例。该站点不仅用于调试。 :)

[编辑]

正如弗洛里斯所说,这个例子假设土地是一条直线,在任何方向。

根据Floris的回答,为了让它适合U形土地,你需要像这样修改你的countC

else
{
    input2[x][y]=2;
    return 1+countC(input2,x-1,y,r1,c1)+
        countC(input2,x+1,y,r1,c1)+
        countC(input2,x,y-1,r1,c1)+
        countC(input2,x,y+1,r1,c1)+
        countC(input2,x+1,y+1,r1,c1)+
        countC(input2,x+1,y-1,r1,c1)+
        countC(input2,x-1,y+1,r1,c1)+
        countC(input2,x-1,y-1,r1,c1);
}

如你所见,你也需要进入对角线。

答案 1 :(得分:0)

您编写的代码可以成为工作程序的一部分 - 换句话说,您的逻辑是正确的。我怀疑你的问题在于“你没有展示的代码”。为了演示,我已经将您的代码转换为完整的工作程序 - 根本不需要更改代码。

请注意,在您编写

时,您正在做一些有潜在危险的事情
if(x<0||x>=r1||y<0||y>=c1||input2[x][y]!=0)

由于编译器“短路”OR语句,当任何一个索引超出范围时,你永远不会评估input2[x][y] - 但我不认为这是你应该依赖的行为。首先测试边界会更安全,并返回0以获得“越界”;然后在单独的if语句中测试该位置的非零值(现在是一个“有效”位置)。

#include <stdio.h>
#include <stdlib.h>

int countC(char* input2[],int x,int y,int r1,int c1)
{

if(x<0||x>=r1||y<0||y>=c1||input2[x][y]!=0) // <<<< dangerous! better have two ifs >>>>
{
    return 0;
}
else
{
    input2[x][y]=2;
    return 1+countC(input2,x-1,y,r1,c1)+countC(input2,x+1,y,r1,c1)+countC(input2,x,y-1,r1,c1)+countC(input2,x,y+1,r1,c1);
}
}
int largestSize(int input1[],char* input2[])
{
int r,c,i,j;
int count=0;
int result=0;
r=input1[0];
c=input1[1];
for(i=0;i<r;i++)
{
    for(j=0;j<c;j++)
    {
        if(input2[i][j]==0)
        {
            count=countC(input2,i,j,r,c);
            if(count>result)
            {
                result=count;
            }
        }
    }
}
return result;
}

// <<< new function added to create a "variable size 2D array"
char **twoDchar(int rc, int cc) {
  char** p;
  int ii;
  p = malloc(rc * sizeof (char*));
  p[0]=malloc(rc * cc * sizeof(char));
  for(ii=1; ii<rc; ii++) {
    p[ii]=p[0]+ii*cc*sizeof(char);
  }
  return p;
}

// <<< added main() function to test the code >>>

int main(void) {
  int dims[]={3,9};
  char land[3][9]={ \
    {0, 1, 1, 0, 1, 0, 0, 0, 1}, \
    {0, 1, 0, 1, 0, 0, 0, 0, 0}, \
    {1, 1, 1, 1, 1, 0, 0, 1, 1}};

  char** lp;
  int ii, jj;
  lp = twoDchar(3,9);
  for(ii=0;ii<3;ii++)
    for(jj=0;jj<9;jj++) {
      lp[ii][jj]=land[ii][jj];
    }
  printf("biggest mass is %d\n", largestSize(dims,lp));
}

当我运行上述内容时,我确实得到了答案10

更新以获取“U形土地”的示例:

  char land[3][9]={\
    {0, 1, 1, 0, 1, 0, 1, 0, 1},\
    {0, 1, 0, 1, 0, 0, 1, 0, 0},\
    {1, 1, 1, 1, 1, 0, 0, 0, 1}};

我按预期得到答案9

注意我在问题首次出现时所做的评论:

  

我建议您包含创建2D“数组”的代码 -   因为你实际上创建了一个数组数组而不是静态2D数组   阵列。重要的是要展示你是如何做到的 - 它可能包含一个   bug,任何人都需要运行你的代码。

现在我仔细看了一下,看起来确实可能是问题的根源(尽管你从来没有展示过你是如何想出2D阵列的。)