这是我在没有额外内存的情况下就地解决这个问题的尝试。这是一个 O(n) 算法。
jpalecek 的算法非常智能,但阅读起来并不直观,至少对我来说不是。我已经尝试过了,它可以工作,但我没有时间理解为什么和 cmets 会很棒。
只要数组不太大,Gracenotes 的算法就很棒。如果数据很大,可能需要动态创建数组。
我的算法的基本思想是通过遵循索引和值对的链来更新数组。例如索引 0 映射到值 3。通过使用值 3 作为索引,您将找到下一个对,即数组中的索引 3 和值 1。基本上我保存下一个索引和值对并更新前一个索引和对值直到我完成链条。
如果你能让它更高效、更优雅或整体更好,我会很感兴趣。
我已经编译并测试了下面的代码,但没有使用任何其他测试输入。我已经为那些希望尝试并更好地理解它是如何工作的人留下了调试输出。
// Array print routine.
void printArray (const char * str_p,int a[], int n)
{
printf ("%s\n", str_p);
for (int i = 0; i < n; i++)
{
printf ("%i ", i);
}
printf ("\n");
for (int i = 0; i < n; i++)
{
printf ("%i ", a[i]);
}
printf ("\n\n");
}
// The main code.
void PermuteTheDamnArray()
{
printArray ("Initial Array", a,n);
int i = 0; // Simply a counter.
int p_ix = 0; // Previous Index.
int p_val = a[0]; // Previous Value.
int n_ix = a[0]; // Next index.
int n_val = a[n_ix]; // Next Value.
for (i = 0; i < n; i++)
{
// Replace.
printf ("Swapping orig (%i,%i) with (%i,%i)\n", n_ix, n_val,p_val, p_ix);
a[p_val] = p_ix;
printArray ("Array after swap", a,n);
// The next index and value pair becomes the new previous index and value pair.
p_ix = n_ix;
p_val = n_val;
printf ("The previous pair is now: (%i,%i)\n", p_ix, p_val);
// Get the next index and value pair.
n_ix = n_val;
n_val = a[n_val];
printf ("The next pair is now: (%i,%i)\n", n_ix, n_val);
}
printArray ("Final Array", a,n);
}
Output:
Swapping orig (3,1) with (3,0)
Array after swap
0 1 2 3
3 2 0 0
The previous pair is now: (3,1)
The next pair is now: (1,2)
Swapping orig (1,2) with (1,3)
Array after swap
0 1 2 3
3 3 0 0
The previous pair is now: (1,2)
The next pair is now: (2,0)
Swapping orig (2,0) with (2,1)
Array after swap
0 1 2 3
3 3 1 0
The previous pair is now: (2,0)
The next pair is now: (0,3)
Swapping orig (0,3) with (0,2)
Array after swap
0 1 2 3
2 3 1 0
The previous pair is now: (0,3)
The next pair is now: (3,0)
Final Array
0 1 2 3
2 3 1 0