用螺旋填充二维数组
Fill two dimensional array with spiral
任务是将二维数组 [N][M] 填入螺旋状,数字从 1 开始。
当其中一个元素(N 或 M)为奇数或两者均为奇数时,我的代码无法运行。
当我使用两个不同的偶数或两个相同的偶数时,它起作用了。
我需要帮助才能做到这一点,这样它在任何情况下都能工作,任何 N 和 M。
p.s。请保留我的代码(不要制作动态数组,保留定义等)
#include <iostream>
#define N 6
#define M 4
int nums = 1;
int p = 1;
int arr[N][M];
using namespace std;
void printArr(){
for (int i = 0; i < N; i++){
for (int j = 0; j < M; j++){
cout << arr[i][j] << "\t";
}
cout << endl;
}
}
void circle (int k){
// levo pravo
for (int i = 0+k; i < M-k; i++){
arr[N-N+k][i] = nums;
nums++;
}
// verh niz
nums--;
for (int i = 0+k; i < N-k; i++){
arr[i][M-1-k] = nums;
nums++;
}
// pravo levo
nums--;
for (int i = M-p; i >= 0+k; i--){
arr[N-1-k][i] = nums;
nums++;
}
// niz verh
nums--;
for (int i = N-p; i > 0+k; i--){
arr[i][0+k] = nums;
nums++;
}
p++;
}
int main(){
if (M<N){
for (int k = 0; k < M/2; k++){
circle(k);
}
} else {
for (int k = 0; k < N/2; k++){
circle(k);
}
}
printArr();
return 0;
}
总而言之,我设法通过两个更改解决了问题:
首先,我们更改主调用的限制,以便我们每次都能到达中心,其次,我们避免覆盖已经填充的索引。在这里,我通过在每次赋值之前使用 if
语句进行检查来停止这种覆盖。但是,可能会有更清洁的解决方案。
测试了各种组合(奇-奇、偶-偶、奇-偶、奇-奇-不相同、奇-奇-相同等)
#include <iostream>
#define N 9
#define M 7
int nums = 1;
int p = 1;
int arr[N][M];
using namespace std;
void printArr(){
for (int i = 0; i < N; i++){
for (int j = 0; j < M; j++){
cout << arr[i][j] << "\t";
}
cout << endl;
}
}
void circle (int k){
// levo pravo
for (int i = 0+k; i < M-k; i++){
if (arr[N-N+k][i] == 0)
arr[N-N+k][i] = nums;
nums++;
}
// verh niz
nums--;
for (int i = 0+k; i < N-k; i++){
if (arr[i][M-1-k] == 0)
arr[i][M-1-k] = nums;
nums++;
}
// pravo levo
nums--;
for (int i = M-p; i >= 0+k; i--){
if (arr[N-1-k][i]==0)
arr[N-1-k][i] = nums;
nums++;
}
// niz verh
nums--;
for (int i = N-p; i > 0+k; i--){
if (arr[i][0+k] == 0)
arr[i][0+k] = nums;
nums++;
}
p++;
}
int main(){
if (M<N){
for (int k = 0; k < (M+1)/2; k++){
circle(k);
}
} else {
for (int k = 0; k < (N+1)/2; k++){
circle(k);
}
}
printArr();
return 0;
}
对于奇数 N
或 M
你应该在最后一次迭代后打印一行。您不能打印圆,因为要打印的表面没有 2 条或更多条线。一种方法是检查 N
或 M
是否为奇数,然后打印一条线来填充螺旋线:https://godbolt.org/z/6oavKGPqf
我已将 vert_line
函数和 hor_line
添加到您的代码中以打印最后一行(垂直或水平)。
void hor_line(int k){
for (int i = 0+k; i < M-k; i++){
arr[N-N+k][i] = nums;
nums++;
}
}
void vert_line(int k){
for (int i = 0+k; i < N-k; i++){
arr[i][M-1-k] = nums;
nums++;
}
}
int main(){
if (M<N){
int k{0};
for (; k < M/2; k++){
circle(k);
}
if (M % 2 != 0){
vert_line(k);
}
} else {
int k{0};
for (; k < N/2; k++){
circle(k);
}
if (N % 2 != 0){
hor_line(k);
}
}
printArr();
return 0;
}
任务是将二维数组 [N][M] 填入螺旋状,数字从 1 开始。
当其中一个元素(N 或 M)为奇数或两者均为奇数时,我的代码无法运行。 当我使用两个不同的偶数或两个相同的偶数时,它起作用了。
我需要帮助才能做到这一点,这样它在任何情况下都能工作,任何 N 和 M。
p.s。请保留我的代码(不要制作动态数组,保留定义等)
#include <iostream>
#define N 6
#define M 4
int nums = 1;
int p = 1;
int arr[N][M];
using namespace std;
void printArr(){
for (int i = 0; i < N; i++){
for (int j = 0; j < M; j++){
cout << arr[i][j] << "\t";
}
cout << endl;
}
}
void circle (int k){
// levo pravo
for (int i = 0+k; i < M-k; i++){
arr[N-N+k][i] = nums;
nums++;
}
// verh niz
nums--;
for (int i = 0+k; i < N-k; i++){
arr[i][M-1-k] = nums;
nums++;
}
// pravo levo
nums--;
for (int i = M-p; i >= 0+k; i--){
arr[N-1-k][i] = nums;
nums++;
}
// niz verh
nums--;
for (int i = N-p; i > 0+k; i--){
arr[i][0+k] = nums;
nums++;
}
p++;
}
int main(){
if (M<N){
for (int k = 0; k < M/2; k++){
circle(k);
}
} else {
for (int k = 0; k < N/2; k++){
circle(k);
}
}
printArr();
return 0;
}
总而言之,我设法通过两个更改解决了问题:
首先,我们更改主调用的限制,以便我们每次都能到达中心,其次,我们避免覆盖已经填充的索引。在这里,我通过在每次赋值之前使用 if
语句进行检查来停止这种覆盖。但是,可能会有更清洁的解决方案。
测试了各种组合(奇-奇、偶-偶、奇-偶、奇-奇-不相同、奇-奇-相同等)
#include <iostream>
#define N 9
#define M 7
int nums = 1;
int p = 1;
int arr[N][M];
using namespace std;
void printArr(){
for (int i = 0; i < N; i++){
for (int j = 0; j < M; j++){
cout << arr[i][j] << "\t";
}
cout << endl;
}
}
void circle (int k){
// levo pravo
for (int i = 0+k; i < M-k; i++){
if (arr[N-N+k][i] == 0)
arr[N-N+k][i] = nums;
nums++;
}
// verh niz
nums--;
for (int i = 0+k; i < N-k; i++){
if (arr[i][M-1-k] == 0)
arr[i][M-1-k] = nums;
nums++;
}
// pravo levo
nums--;
for (int i = M-p; i >= 0+k; i--){
if (arr[N-1-k][i]==0)
arr[N-1-k][i] = nums;
nums++;
}
// niz verh
nums--;
for (int i = N-p; i > 0+k; i--){
if (arr[i][0+k] == 0)
arr[i][0+k] = nums;
nums++;
}
p++;
}
int main(){
if (M<N){
for (int k = 0; k < (M+1)/2; k++){
circle(k);
}
} else {
for (int k = 0; k < (N+1)/2; k++){
circle(k);
}
}
printArr();
return 0;
}
对于奇数 N
或 M
你应该在最后一次迭代后打印一行。您不能打印圆,因为要打印的表面没有 2 条或更多条线。一种方法是检查 N
或 M
是否为奇数,然后打印一条线来填充螺旋线:https://godbolt.org/z/6oavKGPqf
我已将 vert_line
函数和 hor_line
添加到您的代码中以打印最后一行(垂直或水平)。
void hor_line(int k){
for (int i = 0+k; i < M-k; i++){
arr[N-N+k][i] = nums;
nums++;
}
}
void vert_line(int k){
for (int i = 0+k; i < N-k; i++){
arr[i][M-1-k] = nums;
nums++;
}
}
int main(){
if (M<N){
int k{0};
for (; k < M/2; k++){
circle(k);
}
if (M % 2 != 0){
vert_line(k);
}
} else {
int k{0};
for (; k < N/2; k++){
circle(k);
}
if (N % 2 != 0){
hor_line(k);
}
}
printArr();
return 0;
}