我必须插入给定格式的数组
{a1,a2,....,an,b1,b2,...,bn}
为
{a1,b1,a2,b2,a3,b3}
在O(n)时间和O(1)空间中。
示例:
Input - {1,2,3,4,5,6}
Output- {1,4,2,5,3,6}
这是按索引排列元素的顺序:
Initial Index Final Index
0 0
1 2
2 4
3 1
4 3
5 5
通过观察一些例子,我发现ai (i<n/2) goes from index (i) to index (2i)
和bi (i>=n/2) goes from index (i) to index (((i-n/2)*2)+1)
。您可以自己验证。如果我错了请纠正我。
但是,我无法在代码中正确应用此逻辑。
我的伪代码:
for (i = 0 ; i < n ; i++)
if(i < n/2)
swap(arr[i],arr[2*i]);
else
swap(arr[i],arr[((i-n/2)*2)+1]);
它不起作用。
我该如何编写算法来解决此问题?
答案 0 :(得分:2)
元素bn
已经在正确的位置,因此让我们忘记它,而只担心其他N = 2n-1个元素。注意,N总是奇数。
现在可以将问题重新声明为“将元素在每个位置i
移到位置2i % N
”
位置0的项目不会移动,因此让我们从位置1开始。
如果从位置1开始并将其移至位置2%N,则在更换之前必须记住位置2%N处的物品。从位置2%N移到位置4%N,从位置4%N移到8%N,依此类推,直到返回位置1,您可以将剩余的物品放到剩下的插槽中
您保证 返回插槽1,因为N是奇数,并且乘以2 mod则奇数是可逆的。不过,您不不能保证可以覆盖所有职位。整个排列将分成一些循环。
如果您可以从每个周期的一个元素开始此过程,那么您将完成全部工作。问题在于弄清楚哪些完成了,哪些没有完成,因此您不会两次覆盖任何周期。
我认为您不能以满足您的时间和空间限制的方式对任意N执行此操作...但是如果N = 2 x -1对于某些x,则出现此问题容易得多,因为每个周期正好包括某些位模式的循环移位。您可以在每个索引的恒定时间内为每个循环生成单个代表(称为循环领导)。 (我将在最后的附录中描述该过程)
现在,我们有了满足您约束条件的递归算法的基础。
给出[a1...an,b1...bn]
:
找到最大的 x ,使得2 x <= 2n
旋转中间元素以创建[a1...ax,b1...bx,ax+1...an,bx+1...bn]
使用上述过程以线性时间对数组的第一部分进行交织,因为它的模量为2 x -1
递归以交织数组的最后一部分。
由于我们保证要递归的数组的最后部分最大为原始大小的一半,因此对于时间复杂度,我们有这样的递归:
T(N) = O(N) + T(N/2)
= O(N)
请注意,递归是一个尾调用,因此您可以在恒定空间中执行此操作。
Fredricksen和Kessler在名为“一种生成两种颜色的珠子项链的算法”的论文中给出了一种简单的算法。您可以在此处获取PDF:https://core.ac.uk/download/pdf/82148295.pdf
实现很容易。从x 0开始,然后重复:
例如,如果x = 8并且我们在10011111
处,则最低的0是位5。我们将其切换为1,然后从顶部复制余数以得到10110110
。虽然是8-5 = 3,而且3不能除以8,所以这个不是循环的领导者,我们继续下一个。
答案 1 :(得分:0)
我要提出的算法可能不是o(n)。 它不是基于交换元素,而是基于移动元素,如果您有列表而不是数组,则移动元素可能是O(1)。
给出2N个元素,在每次迭代(i)中,将元素置于N / 2 + i的位置,并将其移至位置2 * i
a1,a2,a3,...,an,b1,b2,b3,...,bn
| |
a1,b1,a2,a3,...,an,b2,b3,...,bn
| |
a1,b1,a2,b2,a3,...,an,b3,...,bn
| |
a1,b1,a2,b2,a3,b3,...,an,...,bn
以此类推。
N = 4的示例
1,2,3,4,5,6,7,8
1,5,2,3,4,6,7,8
1,5,2,6,3,4,7,8
1,5,2,6,3,7,4,8
答案 2 :(得分:0)
一个有点复杂的想法是假设每个位置都具有以下值:
1, 3, 5, ..., 2n-1 | 2, 4, 6, ..., 2n
a1,a2, ..., an | b1, b2, ..., bn
然后使用O(n)
的{{3}}中所述的两个排序数组的内联合并时间O(1)
的空间复杂度。但是,我们需要在此过程中管理此索引。
答案 3 :(得分:0)
有一个实用的线性时间*就地算法in this question。包括伪代码和C代码。
<块引用>它涉及将前 1/2 项交换到正确的位置,然后对移动的 1/4 项进行排列,然后对剩余的 1/2 数组重复此操作。
<块引用>解读排列使用了这样一个事实,即左侧项目以交替的“添加到末尾,交换最旧”模式移动到右侧。我们可以用这个规则在这个排列中找到第 i 个索引:
<块引用> <块引用>即使是 i,也到了 i/2。
对于奇数 i,在步骤 (i-1)/2 处将最旧的添加到末尾
*数据移动的次数肯定是O(N)。题问解扰指数计算的时间复杂度。我相信它不比O(lg lg N)差。