题目:用O(1)的空间实现矩阵的转置

为了方便,使用一维数组来分析。所谓矩阵转置,行变列,列变行。在转置的过程中,有的元素位置是不变的;对于变化位置的元素,要求O(1)空间完成,那么这些位置的变化一定是有着规律的。

举例,2×5的矩阵,A={0,1,2,3,4,5,6,7,8,9};转置后为AT={0,5,1,6,2,7,3,8,4,9},探索下标变化:

0->0

1->2->4->8->7->5->1

3->6->3

9->9

这些下标的变化是一些环,如果我们能找到这个环,对环做移动处理,就可以O(1)完成了。

现在的问题是,我们如何知道一个环是已经处理过的,仔细观察,如果一个环被处理过,那么总能找到一个它的后继是小于它的。例如,处理了前三个环的时候,当尝试找下标4打头的环时,一直找4的后继下标,会发现后继1是小于4的,我们就知道4是存在于一条已经处理过的环,跳过。

接下来的问题是如何找到当前元素下标的前驱和后继。先求下标i转置前的下标,即i的前驱,对于m×n的矩阵,转置后为n×m,则一维数组的第i个元素表示的行列为(i/m, i%m),根据转置原理,那么这个元素在转置前的m×n矩阵中所表示的行列为(i%m, i/m),那么i在转置前一维数组中的位置为j=(i%m)×n+(i/m)。同理,下标i转置后的位置j=(i%n)×m+(i/n)。

这样,前驱后继都可以求得,找到环就移动环的元素,如果已处理过则跳过,代码如下:

评论:个人觉得每条环总能找到一个它的后继是小于它的原因在于,每条环开始的第一个位置下标总是整条环中最小的,所以只有第一次能遍历权环并回到开始的点。而之所以每条环开始的第一个位置下标最小,是因为整个数组的遍历过程是从小到大,可以保证比每条环开始的位置小的位置都被遍历过了。

int Pre(int index, int m, int n) // 求前驱
{
    return (index % m) * n + (index / m);
}
 
int Next(int index, int m, int n) // 求后继
{
    return (index % n) * m + (index / n);
}
 
void  move(int * a, int i, int m, int n) // 处理环
{
    int curVal =  a[i];
    int cur = i;
    int pre = Pre(i,m,n);
    while(i != pre)
    {
        a[cur] = a[pre];
        cur = pre;
        pre = Pre(cur,m,n);
    }
    a[cur] = curVal;
}
 
void transpose(int *a, int m, int n)  // 转置
{
    for(int i = 0; i < m*n; ++i)
    {
        int next = Next(i,m,n);
        while(i < next)  // 若大于说明已处理过
        {
            next = Next(next,m,n);
        }
        if(next == i)
        {
            move(a,i,m,n);
        }
    }
}
int main()
{
    int a[10] = {0,1,2,3,4,5,6,7,8,9};
    for(int i = 0; i < 10; ++i)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
    transpose(a,2,5);
    for(int i = 0; i < 10; ++i)
    {
        printf("%d ",a[i]);
    }
    printf("\n");
    return 0;
}

转自:http://www.ahathinking.com/archives/217.html

更多:http://zhiqiang.org/blog/science/computer-science/another-perfect-shuffle-algorithm.html

http://space.itpub.net/67063/viewspace-169250

矩阵转置 O(1)空间的更多相关文章

  1. <矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置>

    //矩阵的基本操作:矩阵相加,矩阵相乘,矩阵转置 #include<stdio.h> #include<stdlib.h> #define M 2 #define N 3 #d ...

  2. 【异构计算】OpenCL矩阵转置

    介绍 矩阵转置,主要的技巧还是利用好local memory ,防止local memory,以及glabol memory的读取尽量是合并读写. 完整代码一: main.cpp代码 #include ...

  3. [转]Python中的矩阵转置

    Python中的矩阵转置 via 需求: 你需要转置一个二维数组,将行列互换. 讨论: 你需要确保该数组的行列数都是相同的.比如: arr = [[1, 2, 3], [4, 5, 6], [7, 8 ...

  4. [置顶] [MATLAB技术贴]漫谈MATLAB矩阵转置

    矩阵转置是matlab最基本的操作了,但这个基本操作,也是很多初学者容易出现问题的地方.本帖通过几个实例演示matlab矩阵转置的操作. 方法一:'  运算符与  .'  运算符 >>a ...

  5. POJ3268 Silver Cow Party(dijkstra+矩阵转置)

    Silver Cow Party Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 15156   Accepted: 6843 ...

  6. 基于visual Studio2013解决C语言竞赛题之0705矩阵转置

     题目 解决代码及点评 /* 5. 写一函数,将一个3×3的矩阵转置. */ #include <stdio.h> #include <stdlib.h> void mai ...

  7. Python小代码_5_二维矩阵转置

    使用列表推导式实现二维矩阵转置 matrix = [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]] print(matrix) matrix_t = [[ro ...

  8. LHC大神问的矩阵转置问题

    数学中线性代数中提到的矩阵转置,其实在我们的业务场景中也有需要的地方,比如LHC大神问到的这个问题 那么如何进行行列转换呢? 代码如下: <?php $array=array( '部门1'=&g ...

  9. c++刷题(15/100)矩阵转置,最深子树

    题目一:矩阵转置 给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9]] 输出 ...

随机推荐

  1. jquery load(URL,FUNCTION(){}) 异步加载页面

    $("#btnSearch").click(function () { var queryUrl = '/Report/LoadInsClassifFileNew'; if ($( ...

  2. SQL Server dbcc checkdb 修复

    默认dbcc checkdb 只做数据库的检测数据库是否完好.不会主动做数据库的修复,要修复数据库,需要数据库设单用模式. 1.repair_allow_data_loss  可能导致数据丢失. 2. ...

  3. WAS

    http://pic.dhe.ibm.com/infocenter/wasinfo/v8r0/index.jsp?topic=%2Fcom.ibm.websphere.express.doc%2Fin ...

  4. (十二)boost库之多线程高级特性

    (十二)boost库之多线程高级特性 很多时候,线程不仅仅是执行一些耗时操作,可能我们还需要得到线程的返回值,一般的处理方法就是定义一个全局状态变量,不断轮训状态,就如我目前维护的一个项目,全局变量定 ...

  5. C语言的本质(28)——C语言与汇编之用汇编写一个Helloword

    为了更加深入理解C语言的本质,我们需要学习一些汇编相关的知识.作为最基本的编程语言之一,汇编语言虽然应用的范围不算很广,但是非常重要.因为它能够完成许多其它语言所无法完成的功能.就拿 Linux 内核 ...

  6. tftp使用方法

    参数说明:-l   是local的缩写,后跟存在于Client的源文件名,或下载Client后               重命名的文件名.          -r   是remote的缩写,后跟Se ...

  7. Eclipse Velocity插件安装

    打开eclipse安装velocity插件,这里有两种eclipse velocity的安装 方式一:不推荐的安装(安装会失败) Help>install new software>add ...

  8. poj1581

    A Contesting Decision Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2519   Accepted: ...

  9. C Deepin指针

    L-value -->标识了一个可以存储结果值的内存存储地址--指针变量 or 普通内存变量; R-value -->数值;

  10. phpadmin

    一晚上都在调试数据库,都要疯了,整理如下: 0.Apache服务器的443端口与VMware的冲突,所以要更改配置文件.设为440就可以(这个随意). 1.因为要远程访问,默认密码为空,所以首先给ro ...