时间复杂度:O(col + sum)(列数+三元组数目,这里没有考虑三元组的构建与后续三元组还原为矩阵)
#include <iostream>
#include <cstring>
using namespace std;
// 假设 row <= 100, col <= 100
const int N = 110;
int cnt[N], row, col;
// A[N]存放col下标的计数数组
int A[N], i, sum;
struct elem
{
int i, j, val;
elem():i(0), j(0), val(0){}
elem(int r, int c, int v):i(r), j(c), val(v){}
} elems[N * N], elems_T[N * N];
// Print函数复杂度写高了
void Print()
{
for(int k = 0; k < row * col; k ++)
{
int a = k / row, b = k % row;
bool flag = true;
for(int t = 0; t < sum; t ++)
{
auto p = elems_T[t];
if(a == p.i && b == p.j)
{
flag = false;
cout << p.val << " ";
}
}
if(flag) cout << 0 << " ";
if(k % row == row - 1) puts("");
}
}
int main()
{
// sum记录非0元素的个数,也就是三元组的个数
cin >> row >> col;
for(i = 0,sum = 0; i< row * col; i ++)
{
int x;
cin >> x;
if(!x) continue;
elems[sum ++] = {i / col, i % col, x};
cnt[i % col] ++;
}
// 下面其实就是前缀和的写法,但是其原数组是从0开始的(便于上面记录elems数组),所以为k-1
// 前缀和数组表示对应列指标开始的地方
for(int k = 1; k < col; k ++)
A[k] += A[k - 1] + cnt[k - 1];
// 其实本质上是计数排序
for(int k = 0; k < sum; k ++)
{
auto u = elems[k];
// 将一个数放到相应位置后,将其对应列指标开始的地方往后移动一位
int t = A[u.j] ++;
elems_T[t] = {u.j, u.i, u.val};
}
Print();
return 0;
}