逆时针遍历2D阵列的周长

时间:2016-06-21 19:40:53

标签: c arrays

这是我关于Stack Overflow的第一个问题,所以如果我没有正确遵循社区准则和惯例,请告诉我。

row 0column 0逆时针(或顺时针)方向遍历2D阵列周边的巧妙方法是什么?(最好不重新访问每个元素)?

直观地说,我可以为每个方向顺序写入四个for循环(即,写一个for循环遍历左列,然后写一个for循环来遍历底行等等)。但是这个解决方案感觉很难编码"。

是否存在"快捷方式"利用这种模式的一些关键洞察力的方法?这种快捷方法在程序运行时方面也会有效吗?

提前致谢。

编辑特异性:

具体来说,我试图从row 0column 0逆时针遍历这个2D数组,并且只打印每个元素一次。

假设数组如下所示:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20

我的预期输出如下: 1, 6, 11, 16, 17, 18, 19, 20, 15, 10, 5, 4, 3, 2

这是我目前的解决方案(此解决方案有效):

//Loop through the left side.
int i;
for (i = 0; i < rows; i++)
    printf("%d, ", array[i][0]);

//Loop through the bottom side.
for (i = 1; i < columns; i++)
    printf("%d, ", array[rows-1][i]);

//Loop through the right side.
for (i = rows-2; i >= 0; i--)
    printf("%d, ", array[i][columns-1]);

//Loop through the top side.
for (i = columns-2; i > 1; i--)
    printf("%d, ", array[0][i]);

//Print the last element.
printf("%d.\n", array[0][1]);

就个人而言,我的解决方案似乎很简单,也很重复。我想知道是否有更有创意的解决方案。

如果需要进一步澄清,请告诉我。

1 个答案:

答案 0 :(得分:1)

就个人而言,我认为你描述为“硬编码”的四个循环实际上是最好和最清晰的解决方案。也就是说,这是一个循环中的两个选项,用于数组[N] [M]:

for(int row = 0, col = 0, i = 0; i < 4;) {
  //process
  switch(i) {
    case 0: 
      if(++row == N)
        ++i;
      break;
    case 1: 
      if(++col == M)
        ++i; 
      break;
    case 2: 
      if(--row == 0)
        ++i;
      break;
    case 3:
      if(--col == 0)
        ++i;
      break;
  }
}

OR

int dirs[][] = {{1, 0}, {0, 1}, {-1, 0}, {0, -1}};

for(int row = 0, col = 0, i = 0; i < 4;) {
  //process
  if( dirs[i][0] && ((row += dirs[i][0]) == 0 || row == N) ||
      dirs[i][1] && ((col += dirs[i][1]) == 0 || col == M))
    ++i;
}

注意:所有与0的比较都可以用否定代替。 (a == 0) == (!a)表示所有整数类型。

说明:

两种解决方案都利用了向一个方向行进的想法,直到达到最大/最小值,并将计数器递增到跟踪状态。一个使用switch语句来处理状态,另一个使用内存中的数组。对于第二种解决方案,如果我们正在改变的事物(行或列)达到最大值或最小值,我们只会切换状态。我们不关心改变0的那个是最大值还是最小值,这不会改变状态。

我将重申,最好的解决方案是使用你提到的四个循环,并避免重复,在每个循环中调用一个函数。