Minimum Swaps 最小次数交换使乱序序列变成递增序列

题目:

      给一个乱序的整型数组,元素值范围是1~100000。比如乱序数组[1,3,2],经过一次交换(3,2),就可以变成有序序列[1,2,3]。

比如给序列[1,3,5,2,4,6,8],经过交换(3,2)变成[1,2,5,3,4,6,8],再交换(5,4)变成[1,2,4,3,5,6,8],再交换(3,5)即可变成有序递增序列[1,2,3,4,5,6,8]。

实现算法和代码讲解:

github: https://github.com/luoqifei/daily-rank


/**
 * 给一个已乱序的数组,数组的值有序后是升序数组,比如,1,3,2,4数组,有序后是1,2,3,4。
 * 给定一个包含1-n的数列,我们通过交换任意两个元素给数列重新排序。求最少需要多少次交换,能把数组排成按1-n递增的顺序,其中,数组长度不超过100。
 */
public class MinMumSwaps {
    static int solve(int[] arr) {
        Map numberToIndex = IntStream.range(0, arr.length).boxed()
                .collect(Collectors.toMap(i -> arr[i], Function.identity()));
//        /**
//         * 首先取得每个值的索引,
//         */
//        HashMap numberToIndex1 = new HashMap<>();
//        for (int i = 0; i < arr.length; i++) {
//            numberToIndex1.put(arr[i],i);
//        }
        int swapNum = 0;
        /**
         * 核心解法,遍历乱序数组每个元素的索引,如果该元素就处于有序数组的索引上,就不需要交换,否则,就将该元素与本该处于这个位置的元素交换
         * 实现:
         * 用一个hashMap存放有序数组元素和它当前的索引
         * 实现一个交换数组元素的方法
         */
        for (int i = 0; i < arr.length; i++) {
            if (arr[i] != i + 1) {//因为序列是连续的而且是从1开始,所以如果序列不在有序数组的索引上
                if(!numberToIndex.containsKey(i+1)){//避免给出的数组不是连续的,比如1,3,5,2,4,6,8,缺少一个7,会null point
                    continue;
                }
                int otherIndex = numberToIndex.get(i + 1);//就从有序序列找到该值的索引

                numberToIndex.put(arr[i], otherIndex);//更新索引map 数值的索引
                numberToIndex.put(i + 1, i);//更新索引map 数值的索引

                swap(arr, i, otherIndex);//交换数组

                swapNum++;
            }
        }
        return swapNum;
    }

    static void swap(int[] arr, int index1, int index2) {
        int temp = arr[index1];
        arr[index1] = arr[index2];
        arr[index2] = temp;
    }
    public static void main(String[] args) {
       // int[] arr = new int[]{2,3,6,1,4,5};
        int[] arr = new int[]{1,3,5,2,4,6,8};
        System.out.println(solve(arr));
    }
 

你可能感兴趣的:(HackerRank)