O(1)空间和O(n)时间的循环置换

时间:2013-10-24 05:59:30

标签: arrays algorithm language-agnostic permutation

我看到一个面试问题要求 Interchange arr[i] and i for i=[0,n-1]

示例:  输入:1 2 4 5 3 0
 回答:5 0 1 4 2 3

解释:a[1]=2 in input , so a[2]=1 in answer so on

我尝试了这个但没有得到正确答案。

我能做的是:for a pair of numbers p and q , a[p]=q and a[q]=p .

任何想法如何改进它是受欢迎的。

FOR(j,0,n-1)
{
    i=j;
    do{
        temp=a[i];
        next=a[temp];
        a[temp]=i;
        i=next;
    }while(i>j);
}
print_array(a,i,n);  

如果它包含一个带有一些解释的伪代码,我会更容易理解你的答案。

编辑:我说它是循环排列所以更改了问题标题。

3 个答案:

答案 0 :(得分:3)

以下是我提出的(Java代码)。

对于x中的每个值a,它会将a[x]设置为x,并将x设置为已覆盖的值(用于a[a[x]] 1}}),并重复直到它回到原始x

我使用负值作为标志来表示该值已经处理过。

运行时间:

由于它只处理每个值一次,因此运行时间为O(n)

<强>代码:

int[] a = {1,2,4,5,3,0};
for (int i = 0; i < a.length; i++)
{
   if (a[i] < 0)
      continue;
   int j = a[i];
   int last = i;
   do
   {
      int temp = a[j];
      a[j] = -last-1;
      last = j;
      j = temp;
   }
   while (i != j);
   a[j] = -last-1;
}
for (int i = 0; i < a.length; i++)
   a[i] = -a[i]-1;
System.out.println(Arrays.toString(a));

答案 1 :(得分:1)

以下是我的建议,O(n)时间,O(1)空间:

void OrderArray(int[] A)
{
    int X = A.Max() + 1;

    for (int i = 0; i < A.Length; i++)
        A[i] *= X;

    for (int i = 0; i < A.Length; i++)
        A[A[i] / X] += i;

    for (int i = 0; i < A.Length; i++)
        A[i] = A[i] % X;
}

一个简短的解释:

我们使用X作为原始数组中值的基本单位(我们将原始数组中的每个值乘以X,这大于A中的任何数字 - 基本上A + 1的长度。所以在任何时候我们都可以通过A[i] / X来检索原始数组的某个单元格中的数字,只要我们没有向该单元格添加超过X

这让我们有两层值,其中A[i] % X表示排序后单元格的值。这两个层不会在整个过程中相交。

完成后,我们会通过执行A从原始值乘以X来清除A[i] = A[i] % X

希望足够干净。

答案 2 :(得分:0)

也许可以通过使用输入排列的图像作为索引:

 void inverse( unsigned int* input, unsigned int* output, unsigned int n )
 {
     for ( unsigned int i = 0; i < n; i++ )
         output[ input[ i ] ] = i;
 }