题目描述
给一个整数数组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;
}