最近参加了技术性书面访谈。通过以下问题得出结论。
我有一个数组如
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}
我无法在约束内得到任何解决方案,任何人都可以提供解决方案或建议吗?
答案 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)
有关可用算法的详细信息,请转至Sorting algorithm页。