一. 代码实现:
package com.app.main.LeetCode.base;
import com.alibaba.fastjson.JSONObject;
/**
* Created with IDEA
* author:Dingsheng Huang
* Date:2020/2/20
* Time:下午3:39
*/
public class QuickSort {
public static void quickSort(int[] arr, int l, int r) {
if (l >= r) {
return;
}
int pivot = arr[l];
int i = l;
int j = r;
while (i < j) {
// 从右边界开始找到第一个小于 pivot的值
while (i < j && arr[j] > pivot) {
j--;
}
if (i < j) {
// 右边界小于 pivot的值放置于左边界
arr[i] = arr[j];
i++;
}
// 从左边界开始找到第一个大于 pivot的值
while (i < j && arr[i] < pivot) {
i++;
}
if (i < j) {
// 左边界大于 pivot的值放置于右边界
arr[j] = arr[i];
j--;
}
}
arr[i] = pivot;
quickSort(arr, l, i - 1);
quickSort(arr, i + 1, r);
}
public static void main(String[] args) {
int[] testArr = new int[]{3, 1, 2, 2, 0};
System.out.println(JSONObject.toJSONString(testArr));
// sort
quickSort(testArr, 0, testArr.length - 1);
System.out.println(JSONObject.toJSONString(testArr));
}
}
二. 时间复杂度证明思路:
快速排序的一次划分算法从两头交替搜索,直到左边界 l 和右边界 r 重合,因此其时间复杂度是O(n);
理想的情况是,每次划分所选择的中间数恰好将当前序列几乎等分,经过log2n趟划分,便可得到长度为1的子表。这样,整个算法的时间复杂度为O(nlog2n)
为什么理想情况是 log2n趟呢?
每次划分都是等分的话,正好可以得到一颗完全二叉树,而二叉树深度即趟数。
即求N 个节点的完全二叉树深度:
根据二叉树性质,具有n个结点完全二叉树的深度为
(注:[ ]表示向下取整)
最坏的情况是,每次所选的中间数是当前序列中的最大或最小元素,这使得每次划分所得的子表中一个为空表,另一子表的长度为原表的长度-1。这样,长度为n的数据表的快速排序需要经过n趟划分,使得整个排序算法的时间复杂度为O(n2) .