我在网上发现了生成某个序列的问题。
A = [A1, A2, ..., AN]
and
where A1 < A2 < ... < Am > Am+1 > ... > AN for some index m, with m between 1 and N inclusive).
我想找到实现这一目标的最小互换
对于Ex
1 8 10 3 7
Swap between 3 and 7 will give me the required seq.
Ans=1
我在社论中找到了这段代码:
boolean[] done = new boolean[n];
for(int i=0;i<n;i++) {
int index = -1;
for(int j=0;j<n;j++) {
if(!done[j] && (index == -1 || values[j] < values[index]))
index = j;
}
int left = 0, right = 0;
for(int j=0;j<index;j++)
if(!done[j])
left++;
for(int j=index+1;j<n;j++)
if(!done[j])
right++;
res += Math.min(left, right);
done[index] = true;
}
return res;
我无法理解代码的作用
我如何找到最小交换?这是一个标准的算法问题。
时间复杂度是O(n ^ 2)这是好的。
答案 0 :(得分:0)
(注意:交换似乎意味着交换两个相邻的元素。)
代码背后的想法如下。必须将最小元素x移动到数组中的第一个或最后一个位置。移动x的交换次数不取决于执行不涉及x的交换。对于每个有效的解决方案,不涉及x的交换是删除了x的数组的解决方案。因此,存在一个最佳解决方案,将x移动到第一个或最后一个位置,然后以递归方式处理剩余的元素。
代码的结构是找到最小的未处理元素(内部循环1; done[j]
是一个标志,指示位置j
处的元素是否已被处理),确定需要多少次交换将其移动到第一个位置(内环2),并确定将其移动到最后位置(内环3)需要多少交换。我们不会对已处理元素进行互换,因为当我们移动当前元素时,这些元素已经被移除了。
通过将合并排序替换为隐式选择排序并使用Fenwick树计算范围内未处理元素的数量,可以将运行时间提高到O(n log n)。