「改進的快速排序」時間複雜度接近O(n)
阿新 • • 發佈:2019-01-23
1.快速排序知識點回顧:
快速排序採用了一種分治的策略,通常稱其為分治法(Divide-and-Conquer)。
平均時間複雜度為:O(nlogn)
最好時間複雜度為:O(nlogn), 每次找的基準數最佳,為每個區間的中值。
最壞時間複雜度為:O(n2), 陣列遞增或者遞減。
空間複雜度:快速排序在系統內部需要一個棧來實現遞迴。若每次劃分較為均勻,則其遞迴樹的高度為 O(lgn), 故遞迴後所需棧空間為 O(lgn) 。最壞情況下,遞迴樹的高度為 O(n), 所需的棧空間為 O(n) 。
該方法的基本思想是:
1.先從數列中取出一個數作為基準數。
2.分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。
3.再對左右區間重複第二步,直到各區間只有一個數。
快速排序程式碼:
int partition(int arr[], const int& left, const int& right) { if(left < right) { medianAsPivot(arr, left, right); int i = left; int j = right; int key = arr[i]; // 首元素作為pivot while(i < j) { while(i<j && arr[j]>=key) j--; if(i < j) arr[i++] = arr[j]; while(i<j && arr[i]<key) i++; if(i < j) arr[j--] = arr[i]; } arr[i] = key; return i; } return left; } // 快速排序遞迴實現 void quickSort(int arr[], const int& left, const int& right) { if(left < right) { int p = partition(arr, left, right); quickSort(arr, left, p-1); quickSort(arr, p+1, right); } }
2.Kth Largest Element:
http://www.lintcode.com/en/problem/kth-largest-element/
要接近O(n)的解法,必須每次選擇區間的中值最為基準值。
void adjustPivot(vector<int> &nums, int left, int right) { int middle = (left & right) + ((left ^ right) >> 1); if(nums[middle] >= min(nums[left], nums[right]) && nums[middle] <= max(nums[left], nums[right])) swap(nums[left], nums[middle]); else if(nums[right] >= min(nums[left], nums[middle]) && nums[right] <= max(nums[left], nums[middle])) swap(nums[left], nums[right]); } int partition(vector<int> &nums, int left, int right) { if(left < right) { adjustPivot(nums, left, right); int pivot = nums[left]; while(left < right) { while(left < right && nums[right] > pivot) right--; if(left < right) nums[left++] = nums[right]; while(left < right && nums[left] <= pivot) left++; if(left < right) nums[right--] = nums[left]; } nums[left] = pivot; } return left; } int kthLargestElement(int k, vector<int> nums) { int size = nums.size(); if(k <= 0 || k > size) return -1; int left = 0; int right = size - 1; while(true) { int position = partition(nums, left, right); if(position < size-k) left = position + 1; else if(position > size-k) right = position - 1; else return nums[size - k]; } }