[英]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. 当
i
和j
超出限制时,或者通过从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.