转置存储在一维数组中的矩阵,无需使用额外的内存

时间:2012-07-16 08:58:01

标签: java c++ algorithm sorting

  

可能重复:
  In-place transposition of a matrix

最近参加了技术性书面访谈。通过以下问题得出结论。

我有一个数组如

testArray = {a1,a2,a3,...an,b1,b2,b3,....bn,c1,c2,c3,.....,cn}

我需要将此数组排序为`

testArray = {a1,b1,c1,a2,b2,c2,a3,b3,c3,.....,an,bn,cn}

约束是我不应该使用额外的内存,不应该使用任何内置函数。 应该编写完整的代码,它可以是任何语言,也可以使用任何数据结构。

例如:

Input: {1,2,3,4,5,6,7,8,9}, n = 3

Output: {1,4,7,2,5,8,3,6,9}

我无法在约束内得到任何解决方案,任何人都可以提供解决方案或建议吗?

4 个答案:

答案 0 :(得分:8)

这只是一个矩阵转置操作。维基百科上的in-place matrix transposition甚至存在问题和解决方案。

没有额外的空间是不可能的,因为你需要至少通过阵列。 O(1)额外的记忆是可能的,时间复杂度会受到严重影响。

该解决方案基于维基百科页面中的跟随循环算法:对于每个单元格,我们将找到循环中索引最小的单元格。如果索引最小的单元格大于或等于(> =)当前单元格的索引,我们将执行链式交换。否则,我们忽略该单元格,因为它已被正确交换。 (松散分析)时间复杂度的上限可以高达O((MN) 2 )(我们通过M * N单元,并且循环只能与总数一样长细胞)。

答案 1 :(得分:4)

不可能性

在没有额外使用内存和任意长度的情况下实现此算法是不可能的,因为您需要一个迭代器来遍历列表并占用空间。

找到正确的交换指数

对于固定长度的数组和固定的 n ,您可以使用矩阵转置算法。 并且为了交换元素y

您正在寻找的算法是矩阵转置算法。 所以你必须在迭代它之后完全交换每个元素。

http://en.wikipedia.org/wiki/Transpose

基本上你必须将 n - th组件中的 m -th元素与 n - 元素交换到 > m - 组件。这可以通过双循环来完成。

m = length(array)/n;
for (i = 0; i < m; i++)
  for (j = 0; j < n;  j++)
  {
     index_1 = i * m + j;
     index_2 = j * m + i
     swap(index_1, index_2);
  }

注意:对于固定的 m n ,此循环可以完全展开,因此 m,i,j 可以用常数代替。

无内存消耗的交换

为了在不使用额外空间的情况下交换每个元素,您可以使用注释中指出的XOR交换算法:

X := X XOR Y
Y := Y XOR X
X := X XOR Y

答案 2 :(得分:1)

在不使用临时变量的情况下交换两个数字(a和b)的最简单方法是这样的:

  b = b + a;
  a = b - a;
  b = b - a;

如果你在一个函数中写下它,那么你就是那里的一部分。如何在不使用临时变量的情况下跟踪在数组中交换的变量,现在就不用了。

请记住选民:他实际上并不需要对数组进行排序,只需交换正确的值。

编辑:这将适用于Java中的大值(在C / C ++中,除非您打开一些非常激进的编译器优化 - 行为未定义,但defaults to sane)。价值观将会四处传播。

第二次编辑 - 一些(相当未经测试的)代码来翻转数组,我认为4个整数超过了内存限制。虽然技术上大规模地使用unthreadsafe,但它可以并行化,因为你最多只访问一次每个阵列位置:

static int[] a = {1,2,3,4,
                  5,6,7,8,
                  9,10,11,12,
                  13,14,15,16};

static int n = 4;

public static void main(String[] args) 
{
    for(int i = 0; i < a.length/n; i++)     //  1 integer
        for(int j = 0; j < n; j++)          //  1 integer
            if(j > i)
                swap(i*n+j, j*n+i);
}

static void swap(int aPos, int bPos)        //  2 integers
{
    if(a[aPos] != a[bPos])
    {
        a[bPos] = a[aPos] + a[bPos];
        a[aPos] = a[bPos] - a[aPos];
        a[bPos] = a[bPos] - a[aPos];
    }
}

如果这误解了这个问题,请道歉;我仔细阅读并无法解决除此之外所需的内容。

答案 3 :(得分:-1)

查看Quicksort algorithm

有关可用算法的详细信息,请转至Sorting algorithm页。