저는 QuickSort로 작업하고 있으며이 문제 에 대해 LeetCode에서이 두 가지 알고리즘을 테스트했습니다 . 두 알고리즘 모두 작동하지만 하나는 다른 알고리즘보다 훨씬 빠르며 그 이유를 이해할 수 없습니다.
이것은 LeetCode의 시간 제한을 초과합니다.
function quickSort(array) {
quickSortHelper(array, 0, array.length - 1);
return array;
}
function quickSortHelper(array, start, end) {
// Edge case
if(start >= end) return;
// Always choose the pivot index at the beginning of the array.
const pivot = start;
// The left index is next to the pivot on the right.
let left = start + 1;
let right = end;
while (right >= left) {
if (array[left] > array[right] && array[right] < array[pivot])
swap(left, right, array);
if (array[left] < array[pivot]) left += 1;
if (array[right] > array[pivot]) right -= 1;
}
swap(pivot, right, array);
// Always sort the smaller sub-array first
const leftIsSmaller = right - 1 - start < end - (right + 1);
if (leftIsSmaller) {
quickSort(array, start, right - 1);
quickSort(array, right + 1, end);
}
else {
quickSort(array, right + 1, end);
quickSort(array, start, right - 1);
}
}
function swap(a, b, array) {
[array[a], array[b]] = [array[b], array[a]];
return array;
}
빅 O :
이것은 LeetCode 시간 제한을 초과하지 않으며 대부분의 제출물보다 훨씬 빠릅니다. 큰 while 루프 안에있는 2 개의 while 루프는 (나에게) 느리게 보이지만 실제로는 더 빠릅니다.
function quickSort(array) {
sortHelper(array, 0, array.length - 1);
return array;
}
function sortHelper(array, start, end) {
if (start >= end) return;
let i = start;
let j = end;
let base = array[i];
while (i < j) {
while (i < j && array[j] >= base) j -= 1; // This makes sense but why this while loop has to happen before the other while loop?
array[i] = array[j]; // this line
while (i < j && array[i] <= base) i += 1;
array[j] = array[i]; // and this line. don't they make you lose access to the values in the array?
}
array[i] = base;
sortHelper(array, start, i - 1);
sortHelper(array, i + 1, end);
}
왜 그런 겁니까?
시간 복잡도에는 차이가 없지만 첫 번째 버전은 종종 동일한 (또는 반대) 데이터 비교를 두 번 이상 수행합니다. 이것은 두 번째 버전에서는 발생하지 않습니다.
예를 들어, 다음 if
의 경우 첫 번째 표현식이 true이고 두 번째는 false이며 여러 번 반복하는 동안이 표현식이 있다고 가정합니다 .
if (array[left] > array[right] && array[right] < array[pivot])
... left
이 첫 번째 표현식이 참일 때 한 반복에서 다음 반복으로 변경되지 않는 점을 감안할 때이 첫 번째 표현식을 여러 번 확인하는 것은 정말 낭비입니다 .
이 극단적 인 예제 어레이를 예로 들어 보겠습니다. [1, 6, 3, 2, 5, 4]
피벗은 1입니다.
모든 반복 동안 right
인덱스는 왼쪽에 도달 할 때까지 감소합니다. 반복 당 비교 횟수는 4 회이므로 5 회 반복하면 20 회가됩니다.
이제 더 빠른 알고리즘을 살펴보십시오. 동일한 입력에 대한 비교 횟수는 첫 번째 내부 루프의 경우 5이고 두 번째 내부 루프의 경우 0입니다 ( 데이터 비교 만 계산 합니다 ).
이것은 극단적 인 예 (20 대 5)이지만 더 많은 무작위 입력에서도 덜 발생합니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다