给定一个正整数数组,当我们从左向右移动时,我们需要用小于它(当前元素)的第一个元素交换每个元素。
实施例
{ 3 , 5 , 12, 2 ,11 }
{ 2 , 3 , 5 , 11, 12 }
蛮力解决方案模拟,以便更好地理解问题
{ 5, 11, 2, 7, 2 }
After first exchange { 2, 11, 5, 7, 2}
After second exchange { 2, 5, 11, 7, 2}
After third exchange { 2, 5, 7, 11, 2}
After fourth exchange { 2, 5, 7, 2, 11}
任何人都可以想到更好的O(n ^ 2)的解决方案 我首先考虑维持一个双端队列,当我们从第一个元素向右移动时,我们可以尝试维持其他元素之间的下一个最小元素。
与第一种情况一样,我会做这样的事情
while i am finding next element of 3, I will maintain a curr_next to 5. If before encountering the next small element for 3, i encounter one of 5, then I will enqueue it but it hardly improve the performance and still O(n^2)
编辑:我们必须从左向右移动。 模拟第一个例子 -
{ _3_ , 5 , 12, 2 ,11 }
{ 2, _5- , 12, 3, 11 }
{ 2, 3, _12_ , 5, 11 }
{ 2, 3, 5, _12_, 11 }
{ 2, 3, 5, 11 , 12 }
答案 0 :(得分:4)
我可以根据Segment Trees的使用建议O(n*logn)
复杂度的解决方案。
<强>算法:强>
构造一对数组(值,索引),它由初始数组元素的值和相应索引组成。我们称之为array_2
按值对获得的数组进行排序。
在此数组上构造Segment Tree,允许我们在给定的时间间隔内找到具有最小索引的元素。我们称之为SegmentTree
按顺序通过值数组(最初给出的值)。对于每个元素array[ i ]
fing必须与之交换的元素如下:
4.1。使用二进制搜索在array_2
中查找当前元素的值。让它在某个位置k
找到。在此之后array_2
位置k
中的所有元素都是原始数组中小于当前元素的元素。正如您稍后将看到的,它们都具有比当前索引更大的索引(因为我们将在第i步之后从i
删除索引为array_2
的元素)。
4.2。现在我们必须在array_2
间隔[0, k-1]
找到索引最小的元素。这可以查询在步骤2中构造的SegmentTree
。在我们获得具有最小索引的元素之后,我们在原始数组中执行相应的交换,在{中交换这些元素的索引 {1}}(因为它们在原始数组中已被更改)。
4.3。对array_2
执行两个更新操作 - 删除当前正在原始数组中处理索引的元素,并更新与当前处理的索引交换的元素的索引值。
执行步骤4.1 - 4.3 SegmentTree
次后,我们将获得目标数组。
<强>复杂度:强>
我们通过原始数组 - n
次迭代。对于每次迭代,我们执行二进制搜索, SegmentTree查询和两个 SegmentTree更新,每个更新需要n
次执行。摘要logn
。
答案 1 :(得分:1)
问题没有说清楚。在我们交换了两个元素后,我们是否从相同的位置继续,并在没有找到更小的元素时向右移动?或者我们在交换后立即向右移动?在第一种情况下,我们最终得到一个排序数组。
在第二种情况下,我会维护一个平衡的元素和索引搜索树。从最左边的元素开始,重复这些步骤:
这种复杂性可能是O(n log n)或其他东西。这是未经测试和未经证实的,使用风险自负。