將陣列排序所需的最小交換次數

2021-09-05 04:04:18 字數 2056 閱讀 6400

給出乙個具有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次就可以復位。如果瓶子更多呢?你可以通過程式設計來解決。輸入格式為兩行 第一行 乙個正...