【问题标题】:Fill two dimensional array with spiral用螺旋填充二维数组
【发布时间】:2026-01-19 14:00:01
【问题描述】:

任务是用数字从 1 开始的螺旋形填充两个维度数组 [N][M]。

当元素之一(N 或 M)为奇数或两者均为奇数时,我的代码不起作用。 当我使用两个不同的偶数或两个相同的偶数时,它会起作用。

我需要帮助才能做到这一点,因此它在任何情况下都可以使用任何 N 和 M。

附言请保留我的代码(不要制作动态数组,保留定义等)

https://pastebin.com/9HufHYBg

#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;
}

【问题讨论】:

  • “不起作用”是什么意思?你能描述一下你观察到的问题吗? It seems to work here 其中N5
  • “其中一个元素”很奇怪:你的意思是 N 还是 M 之一?
  • 是的,抱歉,“N 或 M 是奇数”
  • @DrewDormann 例如尝试 5 和 7。
  • for (int k = 0; k &lt; M/2; k++) --> for (int k = 0; k &lt; (M+1)/2; k++)(main中的其他循环相同)

标签: c++ arrays spiral


【解决方案1】:

总而言之,我设法通过两个更改来解决: 首先,我们更改主调用的限制,以便我们每次都到达中心,其次,我们避免覆盖已经填充的索引。在这里,我通过在每次分配之前使用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;
}

【讨论】:

  • 我想就是这样,我可以检查任何组合,一切正常
  • 顺便说一句,有什么办法可以在不初始化“int p”的情况下做到这一点?
  • 我想是的,我觉得p和k有线性关系,我看看能不能算出来。如果是,那么我们基本上可以将 p 替换为 k 的表达式
  • 确实如此,但如果我们将“p”更改为“k+1”,就会出现问题
  • 你能检查一下吗? ideone.com/vdfd3A 我认为它工作正常。基本上只是删除了全局 p 并将其移至本地。我看不出它不应该工作的任何原因
【解决方案2】:

对于奇数NM,您应该在最后一次迭代之后打印一行。您无法打印圆形,因为要打印的表面没有 2 条或更多条线。一种方法是检查 NM 是否为奇数,然后打印一条线来填充螺旋: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;
}

【讨论】:

  • 9 和 7 还剩下几个 0s。或者 9 和 3,以便更清楚。
  • @ChrisMM 谢谢克里斯。我也注意到了,是的。我最初的 line 代码仅适用于水平线。