배열 크기 이외의 바이트를 할당하지 않고 int 배열에 대한 정렬 알고리즘을 찾고 있는데 두 가지 명령으로 제한됩니다.
스왑 : 다음 인덱스를 현재 인덱스로 교체합니다.
MOVE : 커서를 +1 또는 -1 색인으로 이동합니다.
즉, 비 이웃 인덱스를 교환,도 인덱스를 바꿀 수 없다 100
당신은 그냥 인덱스를 교환 한 후, 10
. 가장 효율적인 알고리즘, 즉 적은 총 이동량을 사용하는 알고리즘은 무엇입니까?
배열 크기 이외의 바이트를 할당하지 않고 int 배열에 대한 정렬 알고리즘을 찾고 있는데 두 가지 명령으로 제한됩니다.
스왑 : 다음 인덱스를 현재 인덱스로 교체합니다.
MOVE : 커서를 +1 또는 -1 색인으로 이동합니다.
즉, 비 이웃 인덱스를 교환,도 인덱스를 바꿀 수 없다 100
당신은 그냥 인덱스를 교환 한 후, 10
. 가장 효율적인 알고리즘, 즉 적은 총 이동량을 사용하는 알고리즘은 무엇입니까?
답변:
버블 쉐이커 의 양방향 버전 인 칵테일 셰이커 정렬을 고려하십시오 . 거품 정렬을 낮음에서 높음으로 설정 한 다음 거품 정렬을 높임에서 낮음으로 설정하고 완료 될 때까지 반복합니다. 이것은 여전히 이지만 어레이의 하이 엔드 근처에있는 작은 요소가 N 패스가 아닌 단일 패스에서 최종 위치로 이동하기 때문에 평균적으로 패스가 훨씬 적습니다. 또한 스왑이 발생한 최저 및 최고 위치를 추적 할 수 있습니다. 후속 패스는 해당 포인트를 넘어 스캔 할 필요가 없습니다.
배열을 주문하는 데 필요한 인접 요소의 스왑 수는 배열의 반전 수와 같습니다. 총 n 개의 요소를 갖는 경우 최대 n * (n-1) / 2 개의 반전이 있으므로 기포 정렬은이 모델에서 점진적으로 최적의 스왑 수를 제공합니다.
부울 플래그를 사용하여 요소를 스왑했는지 여부를 알지 못하는 알고리즘은 다음과 같습니다 (정보를 메모리가 아닌 머신 상태로 유지하는 트릭).
Start:
Do until we are not at the leftmost position (Op 4)
move left (Op 2b)
Check:
If we are at rightmost position (Op 3)
goto Finished:
If current value is larger than next value (Op 5)
goto Unfinished:
move right (Op 2a)
Repeat Check:
Unfinished:
If we are at rightmost position (Op 3)
goto Start:
If current value is larger than next value (Op 5)
swap the elements (Op 1) and move right (Op 2a)
Repeat Unfinished:
Finished:
The list is sorted now, output it.
그놈 정렬 인 Eric Lippert의 솔루션은 기본적으로 양방향 버블 정렬이기 때문에 작동합니다.