思路:
* 每个元素转置前后会形成一个环(一个数字有多个环)
* 利用环来移动元素达到转置
* 关键:
* 1.得到元素下标的前驱后继,
* 2.判断环是否已走过(意味属于一个环的元素一次转置完成)
* 解决:
* 1.从一维下标转二维坐标得到转置后的二维坐标再换回一维坐标
* 如:M*N矩阵
* 假设转置前某个元素的数组下标为i,则它所在行列为(i/N, i%N),
* 转置后所在行列则为(i%N, i/N),可计算转置后数组下标为(i%N)*M+i/N,
* 此为i的后继。假设转置后某个元素的数组下标为i,则它所在行列为(i/M, i%M),
* 则转置前所在行列为(i%M, i/M),可计算此时下标为(i%M)*N+i/M,此为i的前驱。
*
* 2.从一个下标开始直到回到自身没有出现比它小的下标,则环没走过
#include <iostream> using namespace std; #define M 4 #define N 2 int getPrev(int i, int m, int n) { return (i % M) * N + i / M; } int getNext(int i, int m, int n) { return (i % N) * M + i / N; } void moveData(int* arr, int i) { int cur = i; int temp = arr[i]; int prev = getPrev(i, M, N); while (prev != i) { arr[cur] = arr[prev]; cur = prev; prev = getPrev(cur, M, N); } arr[cur] = temp; } void transfer(int* arr, int m, int n) { for (int i = 0; i < m * n; ++i) { int next = getNext(i, m, n); while (i < next) { next = getNext(next, m, n); } //环未走过 if (i == next) { moveData(arr, i); } } } void printMatrix(int* matrix, int m, int n) { for (int i = 0; i < m; ++i) { for (int j = 0; j < n; ++j) { cout << matrix[i * n + j] << " "; } cout << endl; } }