题目:用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. python socket 编程之三:长连接、短连接以及心跳

    长连接:开启一个socket连接,收发完数据后,不立刻关闭连接,可以多次收发数据包. 短连接:开启一个socket连接,收发完数据后,立刻关闭连接. 心跳:长连接在没有数据通信时,定时发送数据包(心跳 ...

  2. JS 禁止浏览器右键菜单和刷新

    <script language="javascript"> //禁止按键F5 document.onkeydown = function(e){ e = window ...

  3. ac命令根据/var/log/wtmp文件登录退出时间计算用户连接时间

    ac命令根据/var/log/wtmp文件登录退出时间计算用户连接时间

  4. Excel在任务栏中只显示一个窗口的解决办法

     Excel在任务栏中只显示一个窗口的解决办法  以前朋友遇到过这个问题,这次自己又遇到了,习惯了以前的那种在任务栏中显示全部窗口,方便用Alt+Tab键进行切换. 如果同时打开许多Excel工作簿, ...

  5. 图片拉伸: stretchableImageWithLeftCapWidth

    - (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight: (NSInteger)topCa ...

  6. Java面向对象知识点精华

  7. swift锁屏播放,音乐进度更新,专辑,歌手名显示

    我自己用的音乐播放器是自带的AVPlayer 导入头文件#import <MediaPlayer/MediaPlayer.h> 远程控制事件接收与处理- (void)viewWillApp ...

  8. js的事件属性方法一览表

    event对象常用属性和方法 event 对象用来表示当前事件,事件有很多状态,例如,鼠标单击时的位置,按下键盘时的按键,发生事件的HTML元素,是否执行默认动作,是否冒泡等,这些都是作为event对 ...

  9. Emmet 插件使用教程

    1)使用 Emmet 生成 HTML 的语法详解生成 HTML 文档初始结构 HTML 文档的初始结构,就是包括 doctype.html.head.body 以及 meta 等内容.你只需要输入一个 ...

  10. 解决UITableView数据没有充满屏幕时,显示多余的空白cell的问题

    #pragma mark 去除多余的线 -(void) clearExtrLine{ UIView *view = [[UIView alloc] init]; view.backgroundColo ...