이번 글에서는 선택 정렬(Selection Sort) 알고리즘을 학습하고,
이를 활용하여 백준 23881번 문제를 Python으로 해결해 본다. 🚀
1. 선택 정렬(Selection Sort)이란?
📌 개념
선택 정렬은 배열에서 최소값(또는 최대값)을 찾아 정렬하는 방식이다.
정렬이 완료될 때까지 이 과정을 반복하여 배열을 정렬한다.
🔹 선택 정렬의 특징
• 시간 복잡도: O(n²)
• 장점: 코드가 단순하여 구현이 쉬움
• 단점: 성능이 낮아 큰 데이터 정렬에는 부적합
🔹 정렬 방식
• 오름차순 정렬: 최소값을 찾아 맨 앞과 교환
• 내림차순 정렬: 최대값을 찾아 맨 뒤와 교환
2. 선택 정렬 예제 (오름차순 정렬)
다음과 같은 리스트가 있다고 보자.
A = [3, 1, 2, 5, 4]
이 리스트를 선택 정렬하면 다음과 같이 진행된다.
[3, 1, 2, 5, 4] → 최소값 1, 0번 index와 swap
[1, 3, 2, 5, 4] → 최소값 2, 1번 index와 swap
[1, 2, 3, 5, 4] → 최소값 3, 2번 index에 있으므로 pass
[1, 2, 3, 5, 4] → 최소값 4, 3번 index와 swap
[1, 2, 3, 4, 5] → 정렬 완료 ✅
3. 백준 23881번 문제 설명
🔗 문제 링크: 백준 23881 - 알고리즘 수업: 선택 정렬 1
📌 문제 요구사항
- N: 배열 A의 크기 (5 ≤ N ≤ 10,000)
- K: K번째 교환된 두 개의 수를 출력 (1 ≤ K ≤ N)
- K번째 교환이 발생하지 않으면 -1을 출력
4. 백준 23881번 선택 정렬 로직 분석
백준 문제에서는 최소값이 아니라 최대값을 찾아서 뒤쪽과 교환하는 방식을 사용한다.
선택 정렬 (최대값을 뒤로 이동시키는 방식)
[3, 1, 2, 5, 4] → 최대값 5, 4번 index와 swap
[3, 1, 2, 4, 5] → 최대값 4, 3번 index에 있으므로 pass
[3, 1, 2, 4, 5] → 최대값 3, 2번 index와 swap
[2, 1, 3, 4, 5] → 최대값 2, 1번 index와 swap
[1, 2, 3, 4, 5] → 정렬 완료 ✅
5. Python 코드 구현
(1) 시간 초과 발생 코드 (비효율적인 방식)
#시간초과 발생한 코드
import sys
#배열 A의 크기 N 과 교환횟수 K 를 입력받는다.
N, K = list(map(int, sys.stdin.readline().rsplit()))
#배열 A의 원소들을 입력받는다.
lst = list(map(int, sys.stdin.readline().rsplit()))
cnt = 0
breakYN = False
#1.배열의 끝부분부터 반복한다.
for i in range(N-1, 0, -1):
last = i
#2.최대값을 찾는다.
for j in range(i-1, -1, -1):
if (lst[j] > lst[last]):
last = j
#3.최대값과 swap. 만약 해당 위치가 최대값이라면 pass
if last != i:
#리스트 값 스왑
lst[i], lst[last] = lst[last], lst[i]
cnt += 1
#4.교환횟수에 도달하면 break
if (cnt == K):
print(lst[last], lst[i])
breakYN = True
break
if breakYN == False:
print(-1)
(2) 시간 초과 해결 코드 (함수 활용 최적화)
#선택정렬 알고리즘으로 시간초과 해결
import sys
#배열 A의 크기 N 과 교환횟수 K 를 입력받는다.
N, K = list(map(int, sys.stdin.readline().rsplit()))
#배열 A의 원소들을 입력받는다.
lst = list(map(int, sys.stdin.readline().rsplit()))
#선택정렬 함수
def selection_sort(N):
cnt = 0
#1.배열의 끝부분부터 반복한다.
for i in range(N-1, 0, -1):
last = i
#2.최대값을 찾는다.
for j in range(i-1, -1, -1):
if (lst[j] > lst[last]):
last = j
#3.최대값과 swap. 만약 해당 위치가 최대값이라면 pass
if last != i:
#리스트 값 스왑
lst[i], lst[last] = lst[last], lst[i]
cnt += 1
#4.교환횟수에 도달하면 break
if (cnt == K):
return (print(lst[last], lst[i]))
return(print(-1))
#선택정렬 함수 호출
selection_sort(N)
6. 예제 입력 & 출력
✅ 예제 1
입력:
5 2
3 1 2 5 4
출력:
2 3
✅ 예제 2
입력:
5 4
3 1 2 5 4
출력:
-1
7. 코드 설명
🔹 입력 받기
N, K = map(int, sys.stdin.readline().split())
lst = list(map(int, sys.stdin.readline().rsplit()))
- N: 배열의 크기
- K: K번째 교환이 발생한 두 개의 값 출력
- lst: 정렬할 배열
🔹 선택 정렬 로직 (최대값을 찾아 뒤로 이동)
for i in range(N - 1, 0, -1):
last = i
- i: 현재 탐색하는 배열 크기 (뒤쪽 정렬된 부분 제외)
- last: 최대값이 있는 위치
🔹 최대값 찾기 & Swap (교환)
for j in range(i - 1, -1, -1):
if lst[j] > lst[last]:
last = j
- lst[j] > lst[last]이면 최대값 위치 갱신
🔹 K번째 교환이 발생하면 작은 값부터 출력 후 종료
if cnt == K:
return (print(lst[last], lst[i]))
🔹 K번 교환이 일어나지 않으면 -1 출력
print(-1)
8. 마무리
이번 글에서는 선택 정렬(Selection Sort) 알고리즘을 이해하고,
백준 23881번 문제를 Python으로 해결해 보았다. 🚀
📌 정리
✅ 선택 정렬은 **O(n²)**의 시간 복잡도를 가짐
✅ K번째 교환된 두 개의 값을 작은 순서대로 출력
✅ K번째 교환이 발생하지 않으면 -1 출력
'코딩라이브러리 > 파이썬' 카테고리의 다른 글
[파이썬] 백준 23968 알고리즘 수업 버블 정렬 1 (0) | 2024.07.01 |
---|---|
[파이썬] 백준 23899 알고리즘 수업 선택 정렬 5 (0) | 2024.06.28 |
[파이썬] 백준 1676 팩토리얼 0의 개수 (factorial n!) (0) | 2024.06.25 |
[파이썬] 백준 6603 로또 (조합 combinations) (0) | 2024.06.24 |
[파이썬] 백준 2309 일곱 난쟁이 (조합 combination) (0) | 2024.06.21 |