題目描述
給一個整數數組nums,將該數組升序排列。
提示
- 1 <= nums.length <= 50000
- 50000 <= nums[i] <= 5000
思路分析
力扣官方給大家提醒,要掌握各種排序方法。
- 冒泡。從左到右依次比較相鄰元素,前大於後則交換,每次冒泡保證最後一個元素是當前最大,再遍歷前 n-1 個元素。
- 選擇。找出前 n 個元素中max,與最後一個元素交換,再找前 n-1 個元素和第 n-1 個元素交換,以此類推。
- 插入。遍歷數組,保證當前元素左邊的數組有序,將當前元素插入對應位置。
- 歸併。分治思想,把數組劃分爲一個一個小塊,再分別排序,然後兩兩合併。合併時,需要用一個輔助數組存儲排序後的序列。
- 計數。當整數範圍不大時使用。創建一個長度爲max-min的數組,統計所有元素出現的次數,再根據次數把元素放回數組,實現排序。
- 桶排。把所有的元素放在一個一個的桶中(看成區間),把每個桶裏的元素排序,最後把桶中元素倒出就是排列好的數組。
- 快排。這裏避免發生極端情況,使用隨機快排。取最後一個元素 right 作爲分界點,把整個數組分爲兩塊/三塊,左邊的元素小於分界點,右邊的元素大於分界點,把分界點移到中間。再對左邊和右邊分別進行相同的操作。
代碼實現
public int[] sortArray(int[] nums) {
if (nums.length < 2) {
return nums;
}
quickSort(nums, 0, nums.length - 1);
bubbleSort(nums);
selectSort(nums);
insertSort(nums);
mergeSort(nums, 0, nums.length - 1);
bucketSort(nums);
return nums;
}
//冒泡排序
public void bubbleSort(int[] nums) {
for (int i = nums.length - 1; i >= 1; i--) {
for (int j = 1; j <= i; j++) {
if (nums[j - 1] > nums[j]) {
swap(nums, j - 1, j);
}
}
}
}
//選擇排序 每次找出n個元素的max放在最後的位置,之後n--
public void selectSort(int[] nums) {
for (int i = nums.length - 1; i >= 1; i--) {
int max = 0;
for (int j = 0; j <= i; j++) {
max = nums[j] > nums[max] ? j : max;
}
swap(nums, i, max);
}
}
//插入排序
public void insertSort(int[] nums) {
for (int i = 1; i < nums.length; i++) {
int j = i;
while (j > 0 && nums[j] > nums[j - 1]) {
swap(nums, j, j - 1);
j--;
}
}
}
//歸併排序
public void mergeSort(int[] nums, int left, int right) {
if (left >= right) {
return;
}
int mid = left + (right - left) / 2;
mergeSort(nums, left, mid);
mergeSort(nums, mid + 1, right);
merge(nums, left, right, mid);
}
public void merge(int[] nums, int left, int right, int mid) {
int[] help = new int[right - left + 1];
int p1 = left, p2 = mid + 1;
int cur = 0;
while (p1 <= mid && p2 <= right) {
help[cur++] = nums[p1] <= nums[p2] ? nums[p1++] : nums[p2++];
}
while (p1 <= mid) {
help[cur++] = nums[p1++];
}
while (p2 <= right) {
help[cur++] = nums[p2++];
}
for (int i = 0; i < help.length; i++) {
nums[left + i] = help[i];
}
}
//計數排序
public void countSort(int[] nums) {
int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE;
for (int num : nums) {
min = Math.min(num, min);
max = Math.max(num, max);
}
int[] count = new int[max - min + 1];
for (int num : nums) {
count[num - min]++;
}
int cur = 0;
for (int i = 0; i < count.length; i++) {
while (count[i] > 0) {
nums[cur++] = i + min;
count[i]--;
}
}
}
//桶排
public void bucketSort(int[] nums) {
//桶大小
int size = 100;
int min = Integer.MIN_VALUE;
int max = Integer.MAX_VALUE;
for (int num : nums) {
min = Math.min(num, min);
max = Math.max(num, max);
}
int count = max - min + 1;
int bucketSize = count % size == 0 ? count / size : count / size + 1;
List<Integer>[] buckets = new List[bucketSize];
//將所有元素入桶
for (int num : nums) {
int quo = (num - min) / size;
if (buckets[quo] == null) {
buckets[quo] = new ArrayList<>();
} else {
buckets[quo].add(num);
}
}
int cur = 0;
for (List<Integer> bucket : buckets) {
if (bucket != null) {
bucket.sort(null);
for (Integer integer : bucket) {
nums[cur++] = integer;
}
}
}
}
//隨機快排
public void quickSort(int[] nums, int left, int right) {
if (left < right) {
//隨機快排
swap(nums, right, left + (int) (Math.random() * (right - left + 1)));
int[] p = process(nums, left, right);
quickSort(nums, left, p[0] - 1);
quickSort(nums, p[1] + 1, right);
}
}
public int[] process(int[] nums, int left, int right) {
int less = left - 1;
int more = right;
while (left < more) {
if (nums[left] < nums[right]) {
swap(nums, left++, ++less);
} else if (nums[left] > nums[right]) {
swap(nums, left, --more);
} else {
left++;
}
}
swap(nums, right, more);
return new int[]{less + 1, more};
}
public void swap(int[] nums, int a, int b) {
int tmp = nums[a];
nums[a] = nums[b];
nums[b] = tmp;
}