使數組有序的最小交換次數
問題是給出一個數組,然後數組裏面的元素可以交換,任意位置都可以交換,然後求使得該數組有序的最小交換次數。
Sample Input 1
2
4
4 3 2 1
5
1 5 4 3 2
Sample Output 1
2
2
示例輸入第一個2是隻有2個測試用例,接下來每個測試用例第一個數是4,代表數組長度是4,下一行就是數組的元素(對python來說這個數組長度這個不太需要)。
解法: 目的是去找數組中互換閉包的個數,若數組本來有n個數,現在找到了一個包含x個數的互換閉包,互換閉包的意思就是在閉包內只需要交換x-1次就可以(其實就是最大交換次數),剩下n-x就得交換n-x次,那麼總交換次數就是x-1+n-x=n-1次。所以,若找到a個這樣的閉包,那麼總交換次數就是n-a次。
注意,互換閉包的長度可以爲1,也就是若當前位置就是該有的數字,那就不需要交換了。
n = int(input().strip())
for repeat_i in range(n):
length = int(input().strip())
line = input()
str_list = line.split(' ')
arr = [int(x) for x in str_list]
# 先排個序,找到每個數字對應的位置
new_arr = sorted(arr)
dict_position = {}
for i in range(len(new_arr)):
dict_position[new_arr[i]] = i
print("dict_position", dict_position)
# 中心思想很簡單,就是針對每一個位置上的數,
# 我假設這個數被換到對應位置上,
# 現在我看一下對應位置上的數有沒有被訪問過
# 如果對應位置上的數沒有被訪問過,
# 那我把對應位置上的數再交換到它對應的位置上,
# 現在我再看看對應位置上的數應該在的位置上那個數有沒有被訪問過
res_closure = 0
flag = [0 for x in arr]
for i in range(len(arr)):
if flag[i] == 0:
print("i",i)
j = i
while flag[j] == 0:
print("j",j)
flag[j] = 1
j = dict_position[arr[j]]
res_closure += 1
print(len(arr) - res_closure)