问题描述: 给你一个整数数组nums
,将该数组升序排列。
使用API就没多大的意义了。
方法一: 快速排序的实现
注意: 快速排序的边界情况还是比较烦人的,注意分情况,而且最后交换的时候一定是和right这个位置交换。
import java.util.Arrays;
class Solution {
public int[] sortArray(int[] nums) {
quickSort(nums, 0, nums.length - 1);
return nums;
}
public void quickSort(int[] nums, int start, int end) {
if (start < end) {
int k = partition(nums, start, end);
quickSort(nums, start, k - 1);
quickSort(nums, k + 1, end);
}
}
public int partition(int[] nums, int start, int end) {
int base = start;
int left = start + 1;
int right = end;
while (left <= right) {//一定要注意取等号的地方
while (left <= right && nums[left] <= nums[base]) {
left++;
}
while (left <= right && nums[right] >=nums[base]) {
right--;
}
if (left < right) {
swap(nums, left, right);
}
}
swap(nums, base, right);//不管什么情况,都是和right交换
return right;
}
private void swap(int[] nums, int a, int b) {
int t = nums[a];
nums[a] = nums[b];
nums[b] = t;
}
public static void main(String[] args) {
int[] nums = {5, 3, 1, 2};
System.out.println(Arrays.toString(new Solution().sortArray(nums)));
}
}
方法二: 归并排序
重在合并算法的理解
import java.util.Arrays;
class Solution {
public int[] sortArray(int[] nums) {
mergeSort(nums, 0, nums.length - 1);
return nums;
}
public void mergeSort(int[] nums, int start, int end) {
if (start < end) {
int mid = start + ((end - start) >> 1);
mergeSort(nums, start, mid);
mergeSort(nums, mid+1, end);
merge(nums,start,mid,end);
}
}
public void merge(int[] nums, int start, int mid, int end) {
int left = start;
int right = mid + 1;
int current = start;
int[] cArr = Arrays.copyOf(nums, nums.length);//因为会修改nums,所以需要一个拷贝
while(left <= mid && right <= end ) {
if(cArr[left] < cArr[right]) {
nums[current] = cArr[left];
left++;
current++;
}else{
nums[current] = cArr[right];
right++;
current++;
}
}
while(left <= mid) {//如果左边还没合并完,继续合并
nums[current] = cArr[left];
left++;
current++;
}
}
public static void main(String[] args) {
int[] nums = {5, 3, 1, 2};
System.out.println(Arrays.toString(new Solution().sortArray(nums)));
}
}
方法三: 堆排序
import java.util.Arrays;
class Solution {
public int[] sortArray(int[] nums) {
minHeapSort(nums, 0, nums.length - 1);
return nums;
}
private static void minHeapSort(int[] array, int start, int end) {
minHeap(array);//数组堆化
for (int i = array.length - 1; i >= 0; i--) {
swap(array, 0, i);//每次都和堆顶和最后一个元素交换
minHeapFixDown(array, 0, i - 1);//调整的范围要减小
}
}
private static void minHeap(int[] array) {
int n = array.length / 2 - 1;
for (int i = n; i >= 0; i--) {
minHeapFixDown(array, i, array.length - 1);
}
}
private static void minHeapFixDown(int[] array, int root, int len) {
//找到左右孩子节点
int lChild = root * 2 + 1;
int rChild = root * 2 + 2;
//找到左右孩子比较小的那个,准备和根节点比较大小
int min = lChild;
if (lChild > len) {
return;
}
if (rChild > len) {
min = lChild;
} else {
if (array[lChild] > array[rChild]) {
min = rChild;
}
}
//和根节点比较,如果小的话,那么不用调整
if (array[root] <= array[min]) {
return;
} else {
//将根节点和较小的节点交换
swap(array, min, root);
}
//递归
minHeapFixDown(array, min, len);
}
private static void swap(int[] nums, int base, int right) {
int t = nums[right];
nums[right] = nums[base];
nums[base] = t;
}
public static void main(String[] args) {
int[] nums = {5, 3, 1, 2};
System.out.println(Arrays.toString(new Solution().sortArray(nums))); //5,3,1,2 按照套路实现大顶堆
}
}