版权声明:转载请注明出处,谢谢。 https://blog.csdn.net/butterfly5211314/article/details/85331673
问题描述(引自拉丁方阵_百度百科):
拉丁方阵(英语:Latin square)是一种 n × n 的方阵,在这种 n x n 的方阵里,恰有 n 种不同的元素,每一种不同的元素在同一行或同一列里只出现一次。
给个形象的例子, 当n=4时:
可以看到 这4个数每行每列都有, 任意一行一列没有重复的数字.
那么给定数字
, 如何求出一个拉丁方阵呢?
其实从上图中很容易看到规律(
从1开始):
第一行,
:
第二行,
:
…
相信已经可以给出结论了:
那么用二维数组实现, 关键代码:
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个节点的单循环链表(不含头哨兵节点), 其数据从头到尾分别是
。
第一行起从第一个节点的值开始数, 第二行从第二个节点的值开始数.
也就是每过一行, 指针指向下一个节点, 指到最后一个, 再向下指, 会自动到第一个,也就是我们要的效果。
关键代码:
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;
}
}
应该说很好想。
完整测试代码如下:
#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;
}
参考:
拉丁方阵_百度百科
欢迎补充指正!