[삽입 정렬 과정]
1. 현재 index에 있는 데이터 값을 선택한다.
2. 현재 선택한 데이터가 정렬된 데이터 범위에 삽입될 위치를 탐색한다.
3. 삽입 위치부터 index에 있는 위치까지 shift 연산을 수행한다.
4. 삽입 위치에 현재 선택한 데이터를 삽입하고 index++ 연산을 수행한다.
5. 전체 데이터의 크기만큼 index가 커질 때까지, 즉 선택할 데이터가 없을 때까지 반복한다.
시간 제한 1초, 실버 III, 백준 11399번
인하은행에는 ATM이 1대밖에 없다. 지금 이 ATM앞에 N명의 사람들이 줄을 서있다. 사람은 1번부터 N번까지 번호가 매겨져 있으며, i번 사람이 돈을 인출하는데 걸리는 시간은 Pi분이다.
사람들이 줄을 서는 순서에 따라서, 돈을 인출하는데 필요한 시간의 합이 달라지게 된다. 예를 들어, 총 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+2+3+3+4 = 13분이 걸리게 된다. 각 사람이 돈을 인출하는데 필요한 시간의 합은 1+3+6+9+13 = 32분이다. 이 방법보다 더 필요한 시간의 합을 최소로 만들 수는 없다.
줄을 서 있는 사람의 수 N과 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어졌을 때, 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 구하는 프로그램을 작성하시오.
첫째 줄에 사람의 수 N(1 ≤ N ≤ 1,000)이 주어진다. 둘째 줄에는 각 사람이 돈을 인출하는데 걸리는 시간 Pi가 주어진다. (1 ≤ Pi ≤ 1,000)
5 # 데이터 개수 3 1 4 3 2
첫째 줄에 각 사람이 돈을 인출하는데 필요한 시간의 합의 최솟값을 출력한다.
32
N(사람 수)
A(자릿수별로 구분해 저장한 리스트)
S(A 합 배열: 각 사람이 인출을 완료하는 데 필요한 시간을 저장)
for i를 1~N만큼 반복:
for j를 i-1~0까지 뒤에서부터 반복:
현재 범위에서 삽입 위치 찾기
for j를 i~insert_point+1까지 뒤에서 반복:
삽입을 위해 삽입 위치에서 i까지 데이터를 한 칸씩 뒤로 밀기
삽입 위치에 현재 데이터 저장
for i를 1~N만큼 반복:
A 리스트를 통한 합 배열 S 만들기
S 리스트의 각 데이터값을 모두 합해 결과 출력
N = int(input())
A = list(map(int, input().split()))
S = [0] * N
for i in range(1, N): # 삽입 정렬
insert_point = i
insert_value = A[i]
for j in range(i-1, -1, -1): # i-1~0 까지 역순으로 반복
if A[j] < A[i]:
insert_point = j + 1
break
if j == 0:
insert_point = 0
for j in range(i, insert_point, -1): # i~insert_point+1 까지 역순으로 반복
A[j] = A[j-1]
A[insert_point] = insert_value
S[0] = A[0]
for i in range(1, N): # 합 배열 만들기
S[i] = S[i-1] + A[i]
sum = 0
for i in range(0, N): # 합 배열 총합 구하기
sum += S[i]
print(sum)
[퀵 정렬 과정]
1. 데이터를 분할하는 pivot을 설정한다.
2. pivot을 기준으로 다음 a~e 과정을 거쳐 데이터를 2개의 집합으로 분리한다.
a. start가 가리키는 데이터가 pivot이 가리키는 데이터보다 작으면 start를 오른쪽으로 1칸 이동한다.
b. end가 가리키는 데이터가 pivot이 가리키는 데이터보다 크면 end를 왼쪽으로 1칸 이동한다.
c. start가 가리키는 데이터가 pivot이 가리키는 데이터보다 크고, end가 가리키는 데이터가 pivot이 가리키는 데이터보다 작으면 start, end가 가리키는 데이터를 swap하고 start는 오른쪽, end는 왼쪽으로 1칸씩 이동한다.
d. start와 end가 만날 때까지 a~e를 반복한다.
e. start와 end가 만나면 만난 지점에서 가리키는 데이터와 pivot이 가리키는 데이터를 비교하여 pivot이 가리키는 데이터가 크면 만난 지점의 오른쪽에, 작으면 만난 지점의 왼쪽에 pivot이 가리키는 데이터를 삽입한다.
3. 분리 집합에서 각각 다시 pivot을 선정한다.
4. 분리 집합이 1개 이하가 될 때까지 과정 1~3을 반복한다.
시간 제한 2초, 실버 V, 백준 11004번
수 N개 A1, A2, ..., AN이 주어진다. A를 오름차순 정렬했을 때, 앞에서부터 K번째 있는 수를 구하는 프로그램을 작성하시오.
첫째 줄에 N(1 ≤ N ≤ 5,000,000)과 K (1 ≤ K ≤ N)이 주어진다.
둘째에는 A1, A2, ..., AN이 주어진다. (-10^9 ≤ Ai ≤ 10^9)5 2 # 데이터 개수, K번째 수 4 1 2 3 5
A를 정렬했을 때, 앞에서부터 K번째 있는 수를 출력한다.
2
N(숫자의 개수) K(K번째 수)
A(숫자 데이터 저장 배열)
# 별도의 함수 구현 부분
퀵 정렬 함수(시작, 종료, k):
피벗 구하기 함수(시작, 종료):
if 피벗 == k: 종료
elif k < 피벗: 퀵 정렬 수행하기(시작, 피벗-1, k)
else: 퀵 정렬 수행하기(피벗+1, 종료, k)
피벗 구하기 함수(시작, 종료):
데이터가 2개인 경우는 바로 비교하여 정렬
M(중앙값)
중앙값을 시작 위치와 swap
pivot(피벗)을 시작 위치 값 A[S]로 저장
i(시작점), j(종료점)
while i <= j:
피벗보다 큰 수가 나올 때까지 i 증가
피벗보다 작은 수가 나올 때까지 j 감소
찾은 i와 j 데이터를 swap
피벗 데이터를 나뉜 두 그룹의 경계 index에 저장하기
경계 index 리턴
퀵 정렬 실행
k번째 데이터 출력
import sys
input = sys.stdin.readline
N, K = map(int, input().split())
A = list(map(int, input().split()))
def quickSort(S, E, K):
global A
if S < E:
pivot = partition(S, E)
if pivot == K: # K번째 수가 pivot이면 더는 구할 필요 없음
return
elif K < pivot: # K가 pivot보다 작으면 왼쪽 그룹만 정렬
quickSort(S, pivot - 1, K)
else:
quickSort(pivot + 1, E, K) # K가 pivot보다 크면 오른쪽 그룹만 정렬
def swap(i, j):
global A
temp = A[i]
A[i] = A[j]
A[j] = temp
def partition(S, E):
global A
if S + 1 == E:
if A[S] > A[E]:
swap(S, E)
return E
M = (S + E) // 2
swap(S, M)
pivot = A[S]
i = S + 1
j = E
while i <= j:
while pivot < A[j] and j > 0:
j = j - 1
while pivot > A[i] and i < len(A) - 1:
i = i + 1
if i <= j:
swap(i, j)
i = i + 1
j = j - 1
# i == j 피벗의 값을 양쪽으로 분리한 가운데에 오도록 설정하기
A[S] = A[j]
A[j] = pivot
return j
quickSort(0, N - 1, K - 1)
print(A[K - 1])