給你一個整數數組 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
思路:快排,或者叫前序二叉樹,排序後端結果是一個二叉搜索樹
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public int[] sortArray(int[] nums) {
sort(nums);
return nums;
}
public static void sort(int[] nums) {
// 爲了避免出現耗時的極端情況,先隨機打亂
//shuffle(nums);
// 排序整個數組(原地修改)
sort(nums, 0, nums.length - 1);
}
private static void sort(int[] nums, int lo, int hi) {
if (lo >= hi) {
return;
}
// 對 nums[lo..hi] 進行切分
// 使得 nums[lo..p-1] <= nums[p] < nums[p+1..hi]
int p = partition(nums, lo, hi);
sort(nums, lo, p - 1);
sort(nums, p + 1, hi);
}
// 對 nums[lo..hi] 進行切分
private static int partition(int[] nums, int lo, int hi) {
int pivot = nums[lo];
// 關於區間的邊界控制需格外小心,稍有不慎就會出錯
// 我這裏把 i, j 定義爲開區間,同時定義:
// [lo, i) <= pivot;(j, hi] > pivot
// 之後都要正確維護這個邊界區間的定義
int i = lo + 1, j = hi;
// 當 i > j 時結束循環,以保證區間 [lo, hi] 都被覆蓋
while (i <= j) {
while (i < hi && nums[i] <= pivot) {
i++;
// 此 while 結束時恰好 nums[i] > pivot
}
while (j > lo && nums[j] > pivot) {
j--;
// 此 while 結束時恰好 nums[j] <= pivot
}
// 此時 [lo, i) <= pivot && (j, hi] > pivot
if (i >= j) {
break;
}
swap(nums, i, j);
}
// 將 pivot 放到合適的位置,即 pivot 左邊元素較小,右邊元素較大
System.out.println("lo"+lo);
System.out.println("j"+j);
swap(nums, lo, j);
return j;
}
// 洗牌算法,將輸入的數組隨機打亂
private static void shuffle(int[] nums) {
Random rand = new Random();
int n = nums.length;
for (int i = 0 ; i < n; i++) {
// 生成 [i, n - 1] 的隨機數
int r = i + rand.nextInt(n - i);
swap(nums, i, r);
}
}
// 原地交換數組中的兩個元素
private static void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
//leetcode submit region end(Prohibit modification and deletion)