题目:用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. Dom4j使用Xpath语法读取xml节点

    我们可以使用Xpath的语法来轻易的读取xml的某个节点[类似于jQuery的选择器]: 使用Xpath语法需要添加新的jaxen-1.1-beta-7.rar 这个jar包 dom4j完整jar包我 ...

  2. Oracle EBS-SQL (PO-14):检查报价单与成本对比.sql

    select distinct         msi.segment1                                               项目        ,msi.de ...

  3. Qt之QTemporaryFile(文件名唯一,且可以自动删除)

    简述 QTemporaryFile类是操作临时文件的I/O设备. QTemporaryFile用于安全地创建一个独一无二的临时文件.临时文件通过调用open()来创建,并且名称是唯一的(即:保证不覆盖 ...

  4. linux之SQL语句简明教程---SUBSTRING

    SQL 中的 substring 函数是用来抓出一个栏位资料中的其中一部分.这个函数的名称在不同的资料库中不完全一样: MySQL: SUBSTR( ), SUBSTRING( ) Oracle: S ...

  5. Oracle 表的常见操作

    --创建表并指定表空间 create table goods( id VARCHAR2(20) primary key, name VARCHAR2(20) NOT NULL, price NUMBE ...

  6. 《github一天一道算法题》:分治法求数组最大连续子序列和

    看书.思考.写代码. /*************************************** * copyright@hustyangju * blog: http://blog.csdn. ...

  7. [DevExpress]图表开发工具类 ChartUtils

    /// <summary> /// 基于.NET 3.5的Chart工具类;对应的DevExpress版本:12.1.7; /// </summary> public stat ...

  8. 从头开始-07.Foundation框架常用结构体

    一.Foundation框架常用结构体NSRange\CGRange.NSPoint\CGPoint.NSSize\CGSize. NSRect\CGRect 的使用 1.  基本使用: //NSRa ...

  9. UIButton 头文件常见属性和方法

    UIButton头文件常见属性 1.属性 contentEdgeInsets: default is UIEdgeInsetsZero.设置内容四边距,默认边距为0 @property(nonatom ...

  10. [IOS]图标尺寸

    最新参考网址:https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/Ico ...