简体   繁体   English

如何以蜗牛模式迭代二维数组,单循环?

[英]How can I iterate through a two-dimensional array in a snail mode, with a single cycle?

Given a two dimensional array , I would like to iterate through it in a snail mode and print out the elements using one single cycle .给定一个二维数组,我想以蜗牛模式迭代它并使用一个循环打印出元素。

For example if the given array is:例如,如果给定的数组是:

10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
25 26 27 28 29
30 31 32 33 34

The program should print out:该程序应打印出:

10 15 20 25 30 31 32 33 34 29 24 19 14 13 12 11 16 21 26 27 28 23 18 17 22

So starting from the upper-left corner and arriving to the center of the array.所以从左上角开始,到达数组的中心。

Here is the solution with one for loop: 这是一个for循环的解决方案:

It works only when the matrix is: n >= m 它仅在矩阵为: n> = m时有效

#include <iostream>

using namespace std;

int main()
{
//    int arr[4][3] = {{0, 9, 8} , {1, 10 , 7} , {2, 11, 6} , {3, 4, 5}};
//    int n = 4, m = 3;

    int arr[4][4] = {{0, 11, 10, 9} , {1, 12, 15, 8} , {2, 13, 14, 7} , {3, 4, 5, 6}};
    int n = 4, m = 4;

    int row = 0, col = 0, turn = 0;
    bool isTop = true;

    for(int nrElem = 0; nrElem <= (n*m); nrElem++)
    {
        //This part make the left, bottom, right part ( U form )
        if((row < n-1-turn) && (col != m-1) && (isTop == true))
        {
            cout << " " << arr[row][col];
            row++;
        } else {
            if((row == n-1-turn) && (col < m-1-turn))
            {
                cout << " " << arr[row][col];
                col++;
            } else {
                if((col == m-1-turn) && (row > 0))
                {
                    cout << " " << arr[row][col];
                    row--;
                } else {
                    isTop = false;
                }
            }
        }
        //

        //And this do the top backward parsing
        if((col > 0) && (isTop == false))
        {
            cout << " " << arr[row][col];
            col--;
        } else {
            if (isTop == false)
            {
                isTop = true;
                turn++;
                row += turn;
                col += turn;
            }
        }
    }

    cout << endl;
    return 0;
}

We can do it with a single cycle without storing additional matrices. 我们可以在一个周期内完成,而无需存储额外的矩阵。 The following code assumes that you can use std::vector from C++11 and is based on the example from geeks for geeks . 下面的代码假设您可以使用来自C++11 std::vector ,并且基于geeks的geeks示例。 Ofcourse, the algorithm works without std::vector as well. 当然,该算法也可以在没有std::vector情况下工作。 Furthermore, this snail goes clockwise and as an exercise you should change it to make counter clockwise :). 此外,这只蜗牛顺时针方向运动,你应该改变它逆时针方向:)。 [I did not compile the code] [我没编译代码]

#include <iostream>
#include <vector>

using namespace std;

void printSnail(vector<vector<int>> const &matrix)
{
  size_t nRow = matrix.size();       // Number of rows that are not printed yet
  size_t nCol = matrix[0].size();    // Number of columns that are not printed yet

  size_t k = 0;
  size_t l = 0;

  // Print all elements in the matrix
  while (k < nRow and l < nCol)
  {
    // Print first row of remaining rows
    for (size_t idx = l; idx < nCol; ++idx)
      cout << matrix[k][idx] << ' ';
    ++k;

    // Print last column of remaining columns
    for (size_t idx = k; idx < nRow; ++idx)
      cout << matrix[idx][nCol - 1] << ' ';
    --nCol;

    // Print last row of remaining rows
    if (k < nRow)
    {
      for (size_t idx = nCol - 1; idx >= l; --idx)
        cout << matrix[nRow - 1][idx] << ' ';
      --nRow;
    }

    // Print the first column of the remaining columns
    if (l < nCol)
    {
      for (size_t idx = nRow - 1; idx >= k; --idx)
        cout << matrix[idx][l] << ' ';
      ++l;
    }
  }
}

Here is a simple solution to your problem: 以下是您的问题的简单解决方案:

  • Keep a 2D array( checkIfVisited ) of the same size(all cells initialized to 0 ) of that your array, in order to keep track of the cells that are already visited. 保持与阵列相同大小的二维数组( checkIfVisited )(所有单元格初始化为0 ),以便跟踪已访问过的单元格。 If (i,j) is 1 then it means that the cell in the original has already been visited. 如果(i,j)1则表示原始单元格已被访问过。

  • We iterate the whole array spirally with the help of the dir variable which keeps track of which direction we are currently traversing. 我们在dir变量的帮助下螺旋地迭代整个数组,该变量跟踪我们当前正在移动的方向。

  • dir = 0 means moving downwards, 1 means moving rightwards, 2 means moving upwards, 3 means moving leftwards. dir = 0表示向下移动, 1表示向右移动, 2表示向上移动, 3表示向左移动。

  • We change directions when either i and j goes out of limits or when the next cell to be traversed has already been traversed before by doing a lookup from the checkIfVisited array. ij超出限制时,或者通过从checkIfVisited数组执行查找之前已经遍历了下一个要遍历的单元格时,我们更改方向。

I have a simple C++ implementation of the above algorithm: 我有一个简单的上述算法的C ++实现:

#include <iostream>
using namespace std;
int main() 
{
    int arr[5][5] = {10, 11, 12, 13, 14,
                     15, 16, 17, 18, 19,
                     20, 21, 22, 23, 24,
                     25, 26, 27, 28, 29,
                     30, 31, 32, 33, 34};

    int checkIfVisited[5][5] = {0,0,0,0,0,
                                0,0,0,0,0,
                                0,0,0,0,0,
                                0,0,0,0,0,
                                0,0,0,0,0};
    int i,j,dir,countVisited;
    dir = 0;
    countVisited = 0;
    i = 0;
    j = 0;
    while(countVisited<5*5)
    {
        cout<<arr[i][j]<<" ";
        checkIfVisited[i][j]=1;
        if(dir==0)
        {
            countVisited++;
            if(i+1>4 || checkIfVisited[i+1][j]==1){
                dir=1;
                j++;
            }
            else
                i++;
        }
        else if(dir==1)
        {
            countVisited++;
            if(j+1>4 || checkIfVisited[i][j+1]==1){
                dir=2;
                i--;
            }
            else
                j++;
        }
        else if(dir==2)
        {
            countVisited++;
            if(i-1<0 || checkIfVisited[i-1][j]==1){
                dir=3;
                j--;
            }
            else
                i--;
        }
        else
        {
            countVisited++;
            if(j-1<0 || checkIfVisited[i][j-1]==1){
                dir=0;
                i++;
            }
            else
                j--;
        }
    }

    return 0;
}

Output: 10 15 20 25 30 31 32 33 34 29 24 19 14 13 12 11 16 21 26 27 28 23 18 17 22 产出: 10 15 20 25 30 31 32 33 34 29 24 19 14 13 12 11 16 21 26 27 28 23 18 17 22

Here is how to implement it in Javascript下面是如何在 Javascript 中实现它

snail = function(arr) {
    let [y, x] = [0, 0];
    let [rs, ls, us, ds] = [0, 0, 0, 0]
    let [xLimit, yLimit] = [arr.length, arr.length];
    let dir = 'right'
    const res = []
    const len = arr[0].length * arr[0].length
    const rowLen = arr[0].length
    while (res.length < len) {
        res.push(arr[y][x])
        switch (dir) {
            case 'right':
                if (x + 1 < xLimit) {
                    x++
                } else {
                    dir = 'down'
                    yLimit = rowLen - ds
                    rs++
                    y++
                }
                break;
            case 'down':
                if (y + 1 < yLimit) {
                    y++
                } else {
                    dir = 'left'
                    xLimit = ls
                    ds++
                    x--
                }
                break;
            case 'left':
                if (x > xLimit) {
                    x--
                } else {
                    dir = 'up'
                    yLimit = ds
                    ls++
                    y--
                }
                break;
            case 'up':
                if (y > yLimit) {
                    y--
                } else {
                    dir = 'right'
                    xLimit = rowLen - rs
                    us++
                    x++
                }
                break;
            default:
                break;
        }

    }
    return res
}

It's not using any built-in Javascript function so it can be translated to any language它没有使用任何内置 Javascript function 所以它可以翻译成任何语言

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM