알고리즘/문제풀이
[백준/Gold2] Swift - 버블 소트
피자식빵
2025. 5. 7. 18:23
2025.05.07 기준 Gold2
https://www.acmicpc.net/problem/1377
알고리즘
정렬
문제 요약
버블 소트 알고리즘을 C++로 작성했다.
bool changed = false;
for (int i=1; i<=N+1; i++) {
changed = false;
for (int j=1; j<=N-i; j++) {
if (A[j] > A[j+1]) {
changed = true;
swap(A[j], A[j+1]);
}
}
if (changed == false) {
cout << i << '\n';
break;
}
}
N은 배열의 크기이고, A는 정렬해야하는 배열이다. 배열은 A[1]부터 사용한다.
위와 같은 소스를 실행시켰을 때, 어떤 값이 출력되는지 구해보자.
제약 조건
- N <= 500,000 (50만 이하의 자연수)
- 둘째 줄부터 N개의 줄에 A[1] ~ A[N]이 주어짐.
- 0 <= A[i] <= 1,000,000인 정수 (100만)
입출력 예
N | A | answer | |
5 | [10, 1, 5, 2, 3] | 3 | |
5 | [1, 3, 5, 7, 9] | 1 |
아이디어
주어진 C++의 버블소트 코드는 O(N^2)이므로 최대 250,000,000,000으로 시간초과가 발생한다.
우선 버블 소트를 1회 진행해보자.

버블 소트가 1회 일어날 때 버블이 되는 원소(10)가 아닌 나머지 원소는 왼쪽으로 한 칸만 이동할 수 있다.

중간에 버블이 되는 원소가 바뀌는 경우에도 2와 3을 보면 정렬이 일어났음을 알 수 있다.
따라서 (A[i]의 처음 인덱스 번호 - A[i]의 정렬 후 인덱스 번호) 를 구하면 A[i]가 정렬되기까지 수행된 버블 소트의 횟수를 알 수 있다.
문제에서 주어진 C++ 코드는 swap이 한 번도 일어나지 않은 시점의 횟수를 출력하고 있으므로 버블 정렬이 일어난 횟수 + 1을 찾으면 된다.
즉, A[i]가 정렬되는데 필요한 버블 소트의 최대 횟수 + 1을 구해야한다.
풀이
- 처음 숫자를 입력받을 때 index 정보를 함께 저장한다.
- 내장 함수 sort()로 정렬 후, 기존 index와 offset의 차이를 구한다.
- 차이의 최댓값이 버블소트를 실행하는 횟수
// 버블 소트를 몇 번째에서 멈추어야 하는지 구하는 문제
// N <= 50만
import Foundation
let N = Int(readLine()!)!
var nums: [(Int, Int)] = [] // 입력 순서: 숫자
for i in 0..<N {
nums.append((i, Int(readLine()!)!))
}
nums.sort { $0.1 < $1.1 } // 숫자를 기준으로 정렬
var answer = 0
nums.enumerated().forEach {
let move = $0.element.0 - $0.offset // 각 숫자의 입력 위치 - 정렬된 위치를 구함
answer = answer < move ? move : answer // (버블 소트 횟수 = 입력 위치 - 정렬된 위치)이므로 최댓값은 버블 소트가 진행되는 횟수임
}
print(answer + 1) // 문제에서 버블 소트가 필요없는 순간을 물어봤기 때문에 버블 소트의 횟수 + 1을 해주어야 함.