小範圍排序是指一個幾乎有序的數組,個別元素需要進行調整,但調整的幅度不超過k,k相對於整個數組很小。
思想:可以使用插入排序,時間複雜度不超過O(N*k)
最好方法是使用堆排序,建立一個k大小的堆,對數組依次進行排序。
題目:
已知一個幾乎有序的數組,幾乎有序是指,如果把數組排好順序的話,每個元素移動的距離可以不超過k,並且k相對於數組來說比較小。請選擇一個合適的排序算法針對這個數據進行排序。
給定一個int數組A,同時給定A的大小n和題意中的k,請返回排序後的數組。
測試樣例:
[2,1,4,3,6,5,8,7,10,9],10,2
返回:[1,2,3,4,5,6,7,8,9,10]
import java.util.*;
public class ScaleSort {
public int[] sortElement(int[] A, int n, int k) {
// write code here
if (A == null || A.length < 1 || n < k) {
return A;
}
int[] heap = getHeap(A, k); // 先建立一個k大小的小根堆
for (int i = k; i < n; i++) {
A[i - k] = heap[0]; // 將調整好的heap[0]轉入A數組內
heap[0] = A[i]; // 將下一個元素放入heap數組中 進行調整
heapify(heap, 0, k);
}
// 此時堆內還剩下一些元素 進行排序
for (int i = n - k; i < n; i++) {
A[i] = heap[0];
swap(heap, 0, k - 1);
heapify(heap, 0, --k);
}
return A;
}
// 初始化k大小的小根堆
public static int[] getHeap(int[] A, int k) {
int[] heap = new int[k];
for (int i = 0; i < k; i++) {
insertHeap(heap, A[i], i);
}
return heap;
}
// 插入值
public static void insertHeap(int[] heap, int value, int i) {
heap[i] = value;
while (i != 0) {
int parent = (i - 1) / 2;
if (heap[parent] > heap[i]) {
swap(heap, parent, i);
i = parent;
} else {
break;
}
}
}
public static void swap(int[] arr, int index1, int index2) {
int tmp = arr[index1];
arr[index1] = arr[index2];
arr[index2] = tmp;
}
/*
* index 對下標爲index的元素進行調整 heapSize heap堆的大小 最後剩餘的堆需要輸出
*/
public static void heapify(int[] heap, int index, int heapSize) {
int left = index * 2 + 1;
int right = index * 2 + 2;
int min = index;
while (left < heapSize) {
if (heap[left] < heap[index]) {
min = left;
}
if (right < heapSize && heap[right] < heap[min]) {
min = right;
}
if (min != index) {
swap(heap, min, index);
} else {
break;
}
index = min;
left = index * 2 + 1;
right = index * 2 + 2;
}
}
}