給出乙個具有n個不同值的陣列a,找出將陣列排序所需的最小交換次數。
第一行包含乙個整數t,表示測試用例的數量。接下來會有t個測試用例,對於每個測試用例,包含乙個整數n表示陣列a中元素的個數,接下來一行為陣列a,包含n個用空格分開的整數。
資料規模:(1<=t<=100; 1<=n<=100; 1<=a[i]<=1000)
對於每個測試用例,輸出乙個整數表示將陣列排序所需的最小交換次數。
陣列a輸出
4 3 2 1
21 5 4 3 2
2
tips:該問題有兩種問法,任意兩個元素均可交換或只能相鄰兩個元素交換。解法不同,本題為任意兩元素可交換。本題解法如下,首先將陣列***a***排序得到***a』*** ,遍歷陣列a中元素,假設當前元素為a[i],
①a[i]在正確的位置(即排序後應在的位置)上,跳過,考慮下一元素。
② 若a[i]不在正確的位置上,假設其排序後的正確位置為j,則將a[i]與a[j]交換。此時i位置上的元素為a[j]的值,記為a[i]』。若a[i]'是在正確的位置上,則停止,否則,重複②步驟。
tips:使用乙個標記陣列,訪問過的元素,不再考慮。例子:
遍歷陣列[1 5 4 3 2],
1在正確的位置上,跳過;
5不在正確的位置上,將其與2交換。2交換到了排序後的正確位置,停止;
4不在正確的位置上,將其與3交換。3交換到了排序後的正確位置,停止;
演算法結束,共交換兩次。
迴圈節
解題思路的1小節中,②步驟的迴圈操作涉及乙個理論概念:迴圈節。
在一次操作中,把該次操作的所有元素都交換到正確位置上的所有操作形成的環,也就是迴圈節。2小節的例子中,有三個迴圈節,分別為【5, 2】;【4, 3】
公式
//假設陣列的迴圈節個數為lops
最小交換次數min_swaps = len(a) - lops
python版本的**實現
def
min_swaps
(nums)
:# mp記錄排序後數值應在的正確位置
mp =
sort_nums =
sorted
(nums)
for i in
range
(len
(sort_nums)):
mp[sort_nums[i]
]= i
# 迴圈節個數
lops =
0# 該位置的數是否被訪問過
flags =
for i in
range
(len
(nums)):
false
)for i in
range
(len
(nums)):
ifnot flags[i]
: j = i
while
not flags[j]
: flags[j]
=true
# j是當前值應在的正確位置
j = mp[nums[j]
] lops +=
1return
len(nums)
- lops
case =
int(
input()
.strip())
while case:
size =
int(
input()
.strip())
nums =
list
(map
(int
,input()
.strip(
).split())
)print
(min_swaps(nums)
) case -=
1
氣泡排序的交換次數 樹狀陣列
計算氣泡排序的交換次數 逆序數概念 在乙個排列中,如果一對數的前後位置與大小順序相反,即前面的數大於後面的數,那麼它們就稱為乙個逆序 乙個排列中所有逆序個數總和叫做這個排列的逆序數。所以氣泡排序結束即是所有的逆序數為0 思路 暴力 我們要計算逆序數,即使要統計出該值位置之前有多少個數比他大.我們用 ...
亂序陣列或字元最小交換次數
如果是要求為只能交換相鄰的兩個元素,使陣列或者是字串間有序 思路 計算陣列中或者是字串間的中元素的逆序數.如 2 1 3 4 此時逆序數為 1 最小交換次數就為1 3 2 1 4 此時逆序數為 3 最小交換次數就為3 include include include include include i...
陣列排序 計算最少交換次數
交換瓶子 有n個瓶子,編號 1 n,放在架子上。比如有5個瓶子 2 1 3 5 4 要求每次拿起2個瓶子,交換它們的位置。經過若干次後,使得瓶子的序號為 1 2 3 4 5 對於這麼簡單的情況,顯然,至少需要交換2次就可以復位。如果瓶子更多呢?你可以通過程式設計來解決。輸入格式為兩行 第一行 乙個正...