问题描述(引自拉丁方阵_百度百科):html
拉丁方阵(英语:Latin square)是一种 n × n 的方阵,在这种 n x n 的方阵里,恰有 n 种不一样的元素,每一种不一样的元素在同一行或同一列里只出现一次。web
给个形象的例子, 当n=4时:
数组
能够看到 这4个数每行每列都有, 任意一行一列没有重复的数字.app
那么给定数字
, 如何求出一个拉丁方阵呢?
其实从上图中很容易看到规律(
从1开始):
第一行,
:
第二行,
:
…svg
相信已经能够给出结论了:
测试
那么用二维数组实现, 关键代码:spa
for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { arr[i][j] = j + 1 + i; if (arr[i][j] > n) { arr[i][j] %= n; } } }
还有一种思路, 就是使用单循环链表, 仔细观察上面的方阵,
能够发现:第1行是从1开始数, 第2行从2开始数,数到最后一个又要从1开始, 这就是个环啊。
因此能够这样:
构造一个含有n个节点的单循环链表(不含头哨兵节点), 其数据从头至尾分别是
。
第一行起从第一个节点的值开始数, 第二行从第二个节点的值开始数.
也就是每过一行, 指针指向下一个节点, 指到最后一个, 再向下指, 会自动到第一个,也就是咱们要的效果。指针
关键代码:code
for (i = 0; i < n; ++i, curr = curr->next) { for (j = 0; j < n; ++j) { int start = curr->data + j; // 第i行开始元素的值 arr[i][j] = start > n ? start % n : start; } }
应该说很好想。orm
完整测试代码以下:
#include <stdio.h> #include <stdlib.h> #include <assert.h> int** genArr(int n) { assert(n > 0); int** arr = (int**)calloc(n, sizeof(int*)); for (int i = 0; i < n; i++) { arr[i] = (int*)calloc(n, sizeof(int)); } return arr; } int** LatinSquare(int n) { int** arr = genArr(n); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { arr[i][j] = j + 1 + i; if (arr[i][j] > n) { arr[i][j] %= n; } } } return arr; } typedef struct Node { int data; struct Node* next; } Node, *LinkedList; int** LatinSquare2(int n) { assert(n > 0); LinkedList list = NULL; Node* head = NULL; Node* curr = NULL; Node* tmp; int i, j; for (int i = 0; i < n; i++) { tmp = (Node*)calloc(1, sizeof(Node)); tmp->data = i + 1; if (!head) { head = tmp; } else { curr->next = tmp; } curr = tmp; } curr->next = head; list = head; curr = head; int** arr = genArr(n); for (i = 0; i < n; ++i, curr = curr->next) { for (j = 0; j < n; ++j) { int start = curr->data + j; // 第i行开始元素的值 arr[i][j] = start > n ? start % n : start; } } tmp = list; for (int i = 0; i < n; i++) { Node* next = tmp->next; free(tmp); tmp = next; } list = NULL; return arr; } int main() { int num = 4; int** arr = LatinSquare(num); for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { printf("%2d", arr[i][j]); } printf("\n"); } if (arr) { for (int i = 0; i < num; i++) { if (arr[i]) { free(arr[i]); } } free(arr); } return 0; }
参考:
拉丁方阵_百度百科
欢迎补充指正!