给你一个整数数组 nums,请你将该数组升序排列。
示例 1:
输入:nums = [5,2,3,1]
输出:[1,2,3,5]
示例 2:
输入:nums = [5,1,1,2,0,0]
输出:[0,0,1,1,2,5]
提示:
1 <= nums.length <= 5 * 104
-5 * 104 <= nums[i] <= 5 * 104
方法1:快速排序
public int[] sortArray(int[] nums) {
QuickSort(nums, 0, nums.length-1);
return nums;
}
/**
* 入口函数(递归方法),算法的调用从这里开始。
*/
public void QuickSort(int[] arr, int startIndex, int endIndex) {
if (startIndex >= endIndex) {
return;
}
// 核心算法部分:双边指针(交换法)
int pivotIndex = doublePointerSwap(arr, startIndex, endIndex);
// 用分界值下标区分出左右区间,进行递归调用
QuickSort(arr, startIndex, pivotIndex - 1);
QuickSort(arr, pivotIndex + 1, endIndex);
}
/**
* 双边指针(交换法)
* 思路:
* 记录分界值 pivot,创建左右指针(记录下标)。
* (分界值选择方式有:首元素,随机选取,三数取中法)
*
* 首先从右向左找出比pivot小的数据,
* 然后从左向右找出比pivot大的数据,
* 左右指针数据交换,进入下次循环。
*
* 结束循环后将当前指针数据与分界值互换,
* 返回当前指针下标(即分界值下标)
*/
private static int doublePointerSwap(int[] arr, int startIndex, int endIndex) {
int pivot = arr[startIndex];
int leftPoint = startIndex;
int rightPoint = endIndex;
while (leftPoint < rightPoint) {
// 从右向左找出比pivot小的数据
while (leftPoint < rightPoint
&& arr[rightPoint] > pivot) {
rightPoint--;
}
// 从左向右找出比pivot大的数据
while (leftPoint < rightPoint
&& arr[leftPoint] <= pivot) {
leftPoint++;
}
// 没有过界则交换
if (leftPoint < rightPoint) {
int temp = arr[leftPoint];
arr[leftPoint] = arr[rightPoint];
arr[rightPoint] = temp;
}
}
// 最终将分界值与当前指针数据交换
arr[startIndex] = arr[rightPoint];
arr[rightPoint] = pivot;
// 返回分界值所在下标
return rightPoint;
}
结果:
方法2:堆排序
public void swap(int[] array, int i, int j){
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
// 堆排序
public void heapSort(int[] array){
int len = array.length;
for (int i = len/2-1; i >= 0 ; i--) {
adjustHeap(array, i, len);
}
for (int i = len - 1; i >= 0 ; i--) {
swap(array, i, 0);
adjustHeap(array, 0, i);
}
}
// 调整堆元素
public void adjustHeap(int[] array, int i, int length){
//先取出当前元素i
int temp = array[i];
//从i结点的左子结点开始,也就是2i+1处开始
for(int k=i*2+1;k<length;k=k*2+1){
//如果左子结点小于右子结点,k指向右子结点(k = i*2+1为左节点,k = i*2+1+1为右节点)
if(k+1<length && array[k]<array[k+1]){
k++;
}
//如果子节点大于父节点,将子节点值赋给父节点(不用进行交换,后续归位)
if(array[k] > temp){
array[i] = array[k];
i = k;
}else{
break;
}
}
//将temp值放到最终的位置
array[i] = temp;
}
结果:
方法3:归并排序
public int[] mergeSort(int[] array, int left, int right){
if(left == right){
return new int[]{array[left]};
}
int mid = (right - left)/2 + left;
int[] leftArray = mergeSort(array, left, mid);
int[] rightArray = mergeSort(array, mid+1, right);
int[] newArray = new int[leftArray.length + rightArray.length];
int index = 0, i = 0, j = 0;
while (i < leftArray.length && j < rightArray.length){
newArray[index++] = leftArray[i] < rightArray[j] ? leftArray[i++] : rightArray[j++];
}
while (i < leftArray.length){
newArray[index++] = leftArray[i++];
}
while (j < rightArray.length){
newArray[index++] = rightArray[j++];
}
return newArray;
}
结果:
方法4:计数排序
public int findMax(int[] array){
// 查找最大值
int max = Integer.MIN_VALUE;
for (int i = 0; i < array.length; i++) {
max = Math.max(max, array[i]);
}
return max;
}
/**
* 查找出最小值
* @param array
* @return
*/
public int findMin(int[] array){
// 查找最大值
int min = Integer.MAX_VALUE;
for (int i = 0; i < array.length; i++) {
min = Math.min(min, array[i]);
}
return min;
}
// 计数排序
public int[] countSort(int[] array){
int max = findMax(array);
int min = findMin(array);
int[] result = new int[array.length];
int temp = max - min + 1;
int[] count = new int[temp];
for (int i = 0; i < array.length; i++) {
count[array[i] - min] += 1;
}
for (int i = 1; i < count.length; i++) {
count[i] += count[i-1];
}
for (int i = array.length-1; i >= 0 ; --i) {
result[--count[array[i]-min]] = array[i];
}
return result;
}
结果:
方法5:希尔排序
//希尔排序
public int[] hillSort(int[] array){
int length = array.length;
int mid = length/2;
while (mid > 0){
for (int i = mid; i < length; i++) {
int temp = array[i];
int index = i-mid;
while (index >= 0 && array[index] > temp){
array[index+mid] = array[index];
index -= mid;
}
array[index + mid] = temp;
}
mid /= 2;
}
return array;
}
结果: