시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
1 초 512 MB 31314 8646 5897 30.188%
문제
N개의 수로 이루어진 수열 A[1], A[2], …, A[N]이 있다. 이 수열에 대해서 버블 소트를 수행할 때, Swap이 총 몇 번 발생하는지 알아내는 프로그램을 작성하시오.버블 소트는 서로 인접해 있는 두 수를 바꿔가며 정렬하는 방법이다. 예를 들어 수열이 3 2 1 이었다고 하자. 이 경우에는 인접해 있는 3, 2가 바뀌어야 하므로 2 3 1 이 된다. 다음으로는 3, 1이 바뀌어야 하므로 2 1 3 이 된다. 다음에는 2, 1이 바뀌어야 하므로 1 2 3 이 된다. 그러면 더 이상 바꿔야 할 경우가 없으므로 정렬이 완료된다.
// NOTE: 입력
3
3 2 1
// NOTE: 출력
3
아니 진짜
이 문제 버블정렬 아니다
병합정렬이다🥹
O(N^2)
O(NlogN)
버블 정렬을 쓰면,
최악의 경우(모두 내림차순으로 정렬된 경우)에 500,000의 제곱만큼 반복해야 한다.
그래서 좀 더 효율적인 병합 정렬을 사용해야 한다.
배열 조작
(merge함수에서 shift와 push를 이용) >> 시간 초과index를 조작
>> 해결!역시 배열의 크기가 클 땐,
배열을 직접 조작하는 메소드는 적합하지 않다.
ex. shift, push 등등
이럴 땐, index를 기억하는 변수를 사용하면 훨씬 빠르게 계산할 수 있다.
const [N, inputs] = require('fs')
.readFileSync('dev/stdin')
.toString()
.trim()
.split('\n');
let _swapCount = 0;
// NOTE: 시간복잡도 O(N^2)인 버블 정렬로 풀면 안됨! >> 병합 정렬 (O(NlogN))
const solution = () => {
const _inputArr = inputs.split(' ').map(v => +v);
mergeSort(_inputArr);
console.log(_swapCount);
};
// NOTE: 병합정렬한 list를 return하는 함수
const merge = (leftList, rightList) => {
const _sortArr = [];
let _leftIdx = 0;
let _rightIdx = 0;
// NOTE: left와 right 둘 중 하나가 빌 때까지
while(_leftIdx < leftList.length && _rightIdx < rightList.length) {
const _isSorted = leftList[_leftIdx] > rightList[_rightIdx];
if (_isSorted) {
_sortArr.push(rightList[_rightIdx++]);
_swapCount += leftList.length - _sortArr.length + _rightIdx;
} else {
_sortArr.push(leftList[_leftIdx++]);
}
}
return [..._sortArr, ...leftList.slice(_leftIdx), ...rightList.slice(_rightIdx)];
};
// NOTE: list를 반갈죽 하는 함수
const mergeSort = (list) => {
if (list.length == 1) return list;
const _mid = Math.ceil(list.length / 2);
const _leftList = list.slice(0, _mid);
const _rightList = list.slice(_mid);
return merge(mergeSort(_leftList), mergeSort(_rightList));
};
solution();