직접 논리구조를 짜보자
처음 받은 값을 기준으로 그 다음으로 작은 값의 위치를 찾는다.
2 5 3 1 이면
2 | 5 3 1 중 가장 작은 것 -> 1 5 3 2
5 | 3 2 중 가장 작은 것 -> 1 2 3 5
2 4 5 3 1 일 때는 어떻게 할까?
2에서 4로 갈 때는 오름차순으로 할 바꿀 필요가 없다. 그러면 나머지 5 3 1 중 가장 작은 것을 4와 바꾼다.
2 4 | 5 3 1 -> 2 1 5 3 4
2 | 1 5 3 4 -> 1 2 5 3 4
1 2 5 | 3 4 -> 1 2 3 5 4
1 2 3 5 | 4 -> 1 2 3 4 5
이때 list.index()을 사용하게 되면 시간복잡도가 O(n)으로 O(n-1!)가 시간 복잡도로 너무 오래 걸리게 된다.
따라서 딕셔너리로 조회를 하면서 해야한다.
새로운 딕셔너리 생성한다.
각 값마다 위치를 키-값 형식으로 저장해 놓는다.
형식은 키 : a[i], 값 : i
딕셔너리에서 조회는 O(1) 밖에 걸리지 않기 때문에 짧은 시간 내에 스왑 횟수를 구할 수 있다.
#!/bin/python3
import math
import os
import random
import re
import sys
#
# Complete the 'lilysHomework' function below.
#
# The function is expected to return an INTEGER.
# The function accepts INTEGER_ARRAY arr as parameter.
#
def lilysHomework(arr):
# Write your code here
sort_array = sorted(arr)
rev_array = list(reversed(arr))
dict_array = {sort_array[i]: i for i in range(n)}
swap_count = 0
i = 0
while i < n:
if sort_array[i] == arr[i]:
i += 1
continue
swap_count += 1
arr[dict_array[arr[i]]], arr[i] = arr[i], arr[dict_array[arr[i]]]
dict_array[sort_array[i]] += 1
dict_array_2 = {sort_array[i]: i for i in range(n)}
swaps_rev = 0
i = 0
while i < n:
if sort_array[i] == rev_array[i]:
i += 1
continue
swaps_rev += 1
rev_array[dict_array_2[rev_array[i]]], rev_array[i] = rev_array[i], rev_array[dict_array_2[rev_array[i]]]
dict_array_2[sort_array[i]] += 1
return min(swap_count, swaps_rev)
if __name__ == '__main__':
fptr = open(os.environ['OUTPUT_PATH'], 'w')
n = int(input().strip())
arr = list(map(int, input().rstrip().split()))
result = lilysHomework(arr)
fptr.write(str(result) + '\n')
fptr.close()