【算法】快速排序
算法 系列博客
【算法】刷題范圍建議 和 代碼規范
【算法】復雜度理論 ( 時間復雜度 )
【字符串】最長回文子串 ( 蠻力算法 )
【字符串】最長回文子串 ( 中心線枚舉算法 )
【字符串】最長回文子串 ( 動態規劃算法 ) ★
【字符串】字符串查找 ( 蠻力算法 )
【字符串】字符串查找 ( Rabin-Karp 算法 )
【算法】雙指針算法 ( 雙指針算法分類 | 相向雙指針 | 有效回文串 )
【算法】雙指針算法 ( 有效回文串 II )
【算法】哈希表 ( 兩數之和 )
【算法】快速排序
文章目錄
- 算法 系列博客
- 一、快速排序思想
- 二、快速排序代碼
一、快速排序思想
快速排序的思想 : 先 整體有序 , 后 局部有序 , 分治算法 ;
先從數組中 挑選出一個數 a , 然后 進行分割 , 將數組分割成兩部分 , 左半部分 小于等于 a , 右半部分 大于等于 a ;
此時數組左半部分肯定小于右半部分 ;
然后分別對 左半部分 和 右半部分 再次挑選一個數 , 進行分割 ;
遞歸進行分割操作 , 直到數組中所有元素排序完成 ;
分割數組時 , 分割條件是小于等于 / 大于等于的原因 :
分割時 , 挑選的數 a , 如果數組元素為 a , 則該元素即可以在左邊 , 又可以在右邊 ;
如果數組中除幾個數之外 , 其它全都是一樣的數 , 如 [1,1,1,1,1,1,1,2] , 挑選數字時 , 大概率選中 1 , 此時如果要求左半部分嚴格小于 1 , 此時 左半部分沒有任何數值 , 很容易出現不均勻的劃分 ;
快速排序的 理想劃分 是每次劃分 , 劃分的左邊和右邊的元素個數基本差不多 , 遞歸時不會出現極端情況 ,
二、快速排序代碼
整數排序 : https://www.lintcode.com/problem/463/
下面代碼中有三個要點
- 分割中心點選取 ;
- 指針限制條件 ;
- 分割時判定要左右交換元素的條件 ;
取中心點, 一般取 start 與 end 索引的 中心索引對應的數組元素值 ;
如下取中間值是強行指定的, 也可以隨機指定 , 指定 start 與 end 之間的一個隨機值 ;
盡量不選取 start 和 end 索引的值 , 如果選取開始/結束值 , 作為分割點 , 假如該數組是按照升序或降序排列 , 可能出現極端情況 ;
指針限制條件 , 分割遍歷時的兩個指針的條件是 left <= right , 這里不能是 left < right ;
如果使用 left < right 會造成死循環遞歸 , 導致棧溢出 ;
使用 [3,2,1,4,5] 進行推導 , 即可出現死循環 ;
判定左右元素交換時 , 必須用 array[left] < pivot 和 array[right] > pivot , 不能使用 array[left] <= pivot 和 array[right] >= pivot , 否則會造成死循環遞歸 , 導致棧溢出 ;
使用 [3,2,1,4,5] 進行推導 , 即可出現死循環 ;
快速排序的時間復雜度是 O(nlog?n)O(n \log n)O(nlogn) ;
代碼示例 :
class Solution {/*** 快速排序* @param A*/public void sortIntegers(int[] A) {if (A == null || A.length == 0) {return;}quickSort(A, 0, A.length - 1);}// 將 array 數組中 start 到 end 之間的元素進行排序private void quickSort(int[] array, int start, int end) {if (start >= end) {// start 如果等于 end, 說明就一個元素, 不用排序// start 正常情況下不會大于 endreturn;}// 設置兩個指針, 分別指向頭尾int left = start, right = end;// 1. 分割操作第一步 : 取中心點// 取中心點, 一般取 start 與 end 索引的中心索引對應的數組元素值// 如下取中間值是強行指定的, 也可以隨機指定 , 指定 start 與 end 之間的一個隨機值// 盡量不選取 start 和 end 索引的值int pivot = array[(start + end) / 2];// 2. 分割操作第二部 : 進行數組元素分割// 注意此處, left 小于等于 right , 不能是小于while (left <= right) {// 找到一個不屬于左邊部分的元素, 將其交換到右邊while (left <= right && array[left] < pivot) {// 如果遇到一個元素不屬于左邊, 則退出循環left++;}// 找到一個不屬于右邊部分的元素, 將其交換到左邊while (left <= right && array[right] > pivot) {// 如果遇到一個元素不屬于右邊, 則退出循環right--;}// 交換上述檢測出來的需要交換的元素if (left <= right) {int tmp = array[left];array[left] = array[right];array[right] = tmp;// 交換完畢后, 繼續向后遍歷left++;right--;}// 交換完畢后, 繼續循環, 該循環退出的條件是 left >= right}// 分割完畢后, 繼續遞歸// 如果按照中心點分割完畢的話, 上面的循環退出, left >= right// 索引的分布如下 : start , right, left, endquickSort(array, start, right);quickSort(array, left, end);} }總結
- 上一篇: 【算法】哈希表 ( 两数之和 )
- 下一篇: 【错误记录】Google Play 上架