HackerRank- Minimum Swap 2 陣列排序最小交換次數
阿新 • • 發佈:2018-12-09
原題:
問題的關鍵是找到閉環。假設每個閉環有k個數字,則閉環內交換次數為k-1。最小交換次數為所有閉環內的交換次數相加。
閉環的含義是,從某個數字A1開始,若A1處於錯誤的index,則找到A2處於A1排序後的位置,找到A3處於A2排序後的位置......最後發現A1處於Ak排序後的位置。則A1,A2... Ak構成一個閉環。
舉例說明 :
7 1 3 2 4 5 6 |
共有1個閉環,包含7 1 2 4 5 6,所以最小交換次數為6-1=5
2 3 1 5 6 4 8 9 7 |
共有3個閉環,分別為(2 3 1), (5 6 4), (8 9 7),所以最小交換次數為2+2+2=6
程式碼如下:
public class MinimumSwap2 { public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int[] arr = new int[n]; for(int i = 0; i < n; ++i) { arr[i] = in.nextInt(); } System.out.println(minimumSwaps(arr)); } public static int minimumSwaps(int[] arr) { Num[] ascArr = new Num[arr.length]; for(int i = 0; i < arr.length; ++i) { ascArr[i] = new Num(i, arr[i]); } Arrays.sort(ascArr, new Comparator<Num>() { @Override public int compare(Num o1, Num o2) { return o1.value - o2.value; } }); int[]visited = new int[arr.length]; int i = 0; int res = 0; int count = 0; while(true) { if(count > 0) { res += (count - 1); count = 0; } int j = 0; for(; j < visited.length; ++j) { if(visited[j] == 0) { if(arr[j] == ascArr[j].value) { visited[j] = 1; } else { i = j; break; } } } if(j >= visited.length) { break; } //找到某個閉環 while(i < arr.length && visited[i] == 0) { if(arr[i] != ascArr[i].value) { visited[i] = 1; i = ascArr[i].ori; ++count; } } } return res; } static class Num { int ori; int value; Num(int index, int val) { ori = index; value = val; } } }