선택 정렬(selection sort)는 대상 데이터에서 최대나 최소 데이터를 데이터가 나열된 순으로 찾아 가며 선택하는 방법이다.
선택 정렬은 구현 방법이 복잡하고, 시간 복잡도도 O(n2)으로 효율적이지 않아 코딩테스트에서는 많이 사용하지 않는다. 선택정렬원리만 간단히 알아보고 넘어가겠다.
최솟값 또는 최댓값을 찾고, 남은 정렬 부분의 가장 앞에 있는 데이터와 swap하는 것이 선택정렬의 핵심이다.
선택 정렬 자체를 묻는 코딩 테스트는 잘 나오지 않지만, 이 원리를 응용하는 문제는 나올 수 있다.
배열을 정렬하는 것은 쉽다. 수가 주어지면 그 수의 각 자릿수를 내림차순으로 정렬하시오
입력
2143
출력
4321
# sort 함수로 풀었을떄
import sys
input = sys.stdin.readline
n = int(input())
arr = []
for i in str(n):
arr.append(int(i))
arr.sort(reverse=True)
answer =''
for i in range(len(arr)):
answer +=''.join(str(arr[i]))
print(answer)
# swap으로 풀었을떄
import sys
input = sys.stdin.readline
n = int(input())
arr = []
for i in str(n):
arr.append(int(i))
for j in range(len(arr)):
# tmp =0
for k in range(j+1,len(arr)):
if arr[j] < arr[k]:
tmp = arr[k]
arr[k] = arr[j]
arr[j] = tmp
answer = ''
for i in range(len(arr)):
answer += ''.join(str(arr[i]))
print(answer)
# 선택정렬 사용
import sys
print = sys.stdout.write
A = list(input())
for i in range(len(A)):
Max = i
for j in range(i+1,len(A)):
#여기서 i+1부터 len(A)까지 A[j]의 가장 큰 인덱스를 구해나가는것
if A[j] > A[Max]:
Max = j
if A[i] < A[Max]:
tmp = A[i]
A[i] = A[Max]
A[Max] = tmp
for i in range(len(A)):
print(A[i])
sys.stdout.write를 선언 하면 리스트에 담은 인풋이 프린트문에 찍히지 않고 오류가 발생하는데, 이 부분은 조금더 확인 해볼 필요가 있을듯.
삽입 정렬(insertion sort)는 이미 정렬된 데이터 범위에 정렬되지 않은 데이터를 적절한 위치에 삽입시켜 정렬하는 방식이다.
시간 복잡도는 O(n2)으로 느린편 이지만 구현하기 쉽다.
선택 데이터를 현재 정렬된 데이터 범위 내에서 적절한 위치에 삽입하는 것이 삽입 정렬의 핵심이다.
적절한 삽입 위치를 탐색하는 부분에서 이진 탐색 (binary search) 등과 같은 탐색 알고리즘을 사용하면 시간 복잡도를 줄일 수 있다.
인하은행에는 ATM이 1대밖에 없다. 지금 이 ATM앞에 N명의 사림이 줄을 서 있다.
사람은 1번에서 N번까지 번호가 매겨져 있으며, i번 사람이 돈을 인출하는데 걸리는 시간은 P(i) 분 이다.
사람들이 줄을 서는 순서에 따라서 돈을 인출하는 데 필요한 시간의 합이 달라진다.
예를 들어 총 5명이 있고, p1 = 3, p2=1, p3=4, p4=3, p5=2 일 때를 생각해보자. [1,2,3,4,5] 순서로 줄을 선다면 1번 사람은 3분만에 돈을 뽑을 수 있다.
2번 사람은 1번 사람이 돈을 뽑을때 까지 기다려야 하므로 3+1 =4 분이 걸린다.
3번 사람은 1,2번 사람이 돈을 뽑을 떄까지 기다려야 하므로 3+1+4 = 8분이 걸린다. 4번 사람은 3+1+4+3 =11분, 5번 사람은 3+1+4+3+2=13분이 걸린다.
즉 각 사람이 돈을 인출하는데 필요한 시간의 합은 3+4+8+11+13 = 39분이다.
근데 만약 [2,5,1,4,3] 순서로 줄을 선다면, 2번은 1분, 5번은 1+2 = 3분, 1번은 1+2+3 = 6분, 4번은 1+2+3+3= 9분, 3번은 1++3+3+4 = 13분이 걸리므로 각 사람이 돈을 인출하는데 필요한 시간의 합은 1+3+6+9+13 = 32분이다.
이 순서보다 모든 사람이 돈을 인출하는데 걸리는 시간이 짧을순 없다
ATM에서 모든 사람이 가장 빠른 시간에 인출하는 방법을 그리디 방식으로 해결해 봅니다.
ATM 앞에 있는 사람 중 인출 시간이 가장 적게 걸리는 사람이 먼저 인출할 수 있도록 순서를 정하는 것이 곧 그리디 방식이다.
그리고 이를 위해서 인출시간을 기준으로 값을 정렬해야 한다.
N의 최댓값이 1000이고, 시간제한이 1초이므로 시간 복잡도가 O(n2)이하인 정렬 알고리즘 중 아무거나 사용해도 된다.
여기는 삽입 정렬을 이용해보자. 정렬을 마친 후에는 각 사람이 인출하는데 필요한 시간을 더하면 되겠네요.
줄을 서있는 사람의 수 N과 각 사람이 돈을 인출하는데 걸리는 시간 P가 주어졌을때 각 사람이 돈을 인출하는데 걸리는 최소 시간을 구하시오
입력
5
3 1 4 3 2
출력
32
n = int(input())
arr = list(map(int,input().split()))
sumarr = [0]*n
for i in range(1,n):
insert_point = i
insert_value = arr[i]
for j in range(i-1,-1,-1):
if arr[j] < arr[i]:
insert_point = j + 1
break
if j == 0:
insert_point = 0
for j in range(i,insert_point,-1):
arr[j] = arr[j-1]
arr[insert_point] = insert_value
sumarr[0] = arr[0]
for i in range(1,n):
sumarr[i] = sumarr[i-1] + arr[i]
print(sum(sumarr))
for i in range(시작,끝,갭)
ex. for i in range(5,0,-1) ==> 5부터 1까지 -1씩 줄여가겠다. (끝 값은 포함 안하니깐 5 부터 1까지 ) => 5,4,3,2,1
ex. for i in range(5,-1,-1) ==> 5부터 1까지 -1씩 줄여가겠다. (끝 값은 포함 안하니깐 5 부터 1까지 ) => 5,4,3,2,1,0
ex. for i in range(0,5,2) ==> 0부터 5까지 2씩 늘랴가겠다. (끝 값은 포함 안하니깐 0부터 4까지) => 0,1,2,3,4