查找数组中的最小交换

时间:2014-10-02 09:29:35

标签: java algorithm

我在网上发现了生成某个序列的问题。

 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)这是好的。

1 个答案:

答案 0 :(得分:0)

(注意:交换似乎意味着交换两个相邻的元素。)

代码背后的想法如下。必须将最小元素x移动到数组中的第一个或最后一个位置。移动x的交换次数不取决于执行不涉及x的交换。对于每个有效的解决方案,不涉及x的交换是删除了x的数组的解决方案。因此,存在一个最佳解决方案,将x移动到第一个或最后一个位置,然后以递归方式处理剩余的元素。

代码的结构是找到最小的未处理元素(内部循环1; done[j]是一个标志,指示位置j处的元素是否已被处理),确定需要多少次交换将其移动到第一个位置(内环2),并确定将其移动到最后位置(内环3)需要多少交换。我们不会对已处理元素进行互换,因为当我们移动当前元素时,这些元素已经被移除了。

通过将合并排序替换为隐式选择排序并使用Fenwick树计算范围内未处理元素的数量,可以将运行时间提高到O(n log n)。