为什么排序算法重要?
问题系统熵决定了一个问题被解决的难易程度
快速排序的基础知识
基位赋值
基准的选择对效率的影响很大
从 c++ STL学习快速排序
- 单边递归法
- 无监督partition方法
- 三点取中法
- 小数据规模,停止快排过程
- 使用插入排序进行首尾
const int threshold = 16;
inline int median(int a, int b, int c){
if(a > b) swap(a, b);
if(a > c) swap(a, c);
if(b > c) swap(b, c);
return b;
}
void __quick_sort(vector<int> &arr, int l, int r){
while(r - l > threshold){
int x = l, y = r, base = median(arr[l], arr[(l + r) / 2], arr[r]);
do{
while(arr[x] < base) x++;
while(arr[y] > base) y--;
if(x <= y){
swap(arr[x], arr[y]);
x++, y--;
}
} while(x <= y);
__quick_sort(arr, x, r);
r = y;
}
return;
}
void final_insert_sort(vector<int> &arr, int l, int r){
int ind = l;
for(int i = l; i <= r; i++){
if(arr[i] < arr[ind]) ind = i;
}
while(ind > l){
swap(arr[ind], arr[ind - 1]);
--ind;
}
for(int i = l + 1; i <= r; i++){
int j = i;
while(arr[j] < arr[j - 1]){
swap(arr[j], arr[j - 1]);
j--;
}
}
return;
}
void quick_sort(vector<int> &arr, int l, int r){
__quick_sort(arr, l , r);
final_insert_sort(arr, l ,r);
return;
}
经典面试题 - 快速排序基础
912. 排序数组
class Solution {
public:
const int threshold = 16;
inline int median(int a, int b, int c){
if(a > b) swap(a, b);
if(a > c) swap(a, c);
if(b > c) swap(b, c);
return b;
}
void __quick_sort(vector<int> &arr, int l, int r){
while(r - l > threshold){
int x = l, y = r, base = median(arr[l], arr[(l + r) / 2], arr[r]);
do{
while(arr[x] < base) x++;
while(arr[y] > base) y--;
if(x <= y){
swap(arr[x], arr[y]);
x++, y--;
}
} while(x <= y);
__quick_sort(arr, x, r);
r = y;
}
return;
}
void final_insert_sort(vector<int> &arr, int l, int r){
int ind = l;
for(int i = l; i <= r; i++){
if(arr[i] < arr[ind]) ind = i;
}
while(ind > l){
swap(arr[ind], arr[ind - 1]);
--ind;
}
for(int i = l + 1; i <= r; i++){
int j = i;
while(arr[j] < arr[j - 1]){
swap(arr[j], arr[j - 1]);
j--;
}
}
return;
}
void quick_sort(vector<int> &arr, int l, int r){
__quick_sort(arr, l , r);
final_insert_sort(arr, l ,r);
return;
}
vector<int> sortArray(vector<int>& nums) {
quick_sort(nums, 0 ,nums.size() - 1);
return nums;
}
};
剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
class Solution {
public:
vector<int> exchange(vector<int>& nums) {
if(nums.size() == 0) return nums;
int x = 0, y = nums.size() - 1;
do{
while(x < nums.size() && nums[x] % 2){
x++;
}
while(y >= 0 && nums[y] % 2 == 0){
y--;
}
if(x <= y){
swap(nums[x], nums[y]);
x++, y--;
}
} while(x <= y);
return nums;
}
};
148.排序链表
class Solution {
public:
ListNode* sortList(ListNode* head) {
if(head == NULL) return head;
int l = head->val, r = head->val;
double mid;
ListNode *p = head, *q, *h1 = NULL, *h2 = NULL;
while(p){
l = min(p->val, l);
r = max(p->val, r);
p = p->next;
}
if(l == r) return head;
mid = (l + r) / 2.0;
p = head;
while(p){
q = p->next;
if(p->val <= mid){
p->next = h1;
h1 = p;
}else{
p->next = h2;
h2 = p;
}
p = q;
}
h1 = sortList(h1);
h2 = sortList(h2);
p = h1;
while(p->next) p = p->next;
p->next = h2;
return h1;
}
};
面试题 17.14. 最小K个数
class Solution {
public:
int getmid(int a, int b, int c){
if(a > b) swap(a, b);
if(a > c) swap(a, c);
if(b > c) swap(b, c);
return b;
}
void quick_select(vector<int> &arr, int l, int r, int k){
if(l >= r) return;
int x = l, y = r, mid = getmid(arr[l], arr[(l + r)/2], arr[r]);
do {
while(arr[x] < mid) x++;
while(arr[y] > mid) y--;
if(x <= y){
swap(arr[x], arr[y]);
x++, y--;
}
}while(x <= y);
if(y - l == k - 1) return; // 当左区间数量等于k,直接返回
if(y - l >= k){ // 左区间数量大于k,继续扩大
quick_select(arr, l, y, k);
}else{
quick_select(arr, x, r, k - x + l);
}
return;
}
vector<int> smallestK(vector<int>& arr, int k) {
vector<int> ans;
if(k == 0) return ans;
quick_select(arr, 0, arr.size() - 1, k);
while(k) ans.push_back(arr[--k]);
return ans;
}
};
95. 不同的二叉搜索树 II
class Solution {
public:
vector<TreeNode*> dfs(int l, int r){
vector<TreeNode*> ans;
if(l > r){
ans.push_back(nullptr);
return ans;
}
for(int i = l; i <= r; i++){
vector<TreeNode *> left_tree = dfs(l, i - 1);
vector<TreeNode *> right_tree = dfs(i + 1, r);
// eg : i = 3
for(TreeNode* left : left_tree){
for(TreeNode* right: right_tree){
TreeNode* t = new TreeNode(i, left, right);
ans.push_back(t);
}
}
}
return ans;
}
vector<TreeNode*> generateTrees(int n) {
vector<TreeNode*> ans;
if(n == 0) return ans;
return dfs(1, n);
}
};
394. 字符串解码
class Solution {
public:
string decodeString(string s) {
string ret;
int i = 0;
while(s[i]){
if(s[i] < '0' || s[i] > '9'){
ret += s[i];
i++;
}else{
int num = 0;
while(s[i] >= '0' && s[i] <= '9'){
num = num * 10 + s[i++] - '0';
}
i++;
int l = i, r = i, cnt = 1;
while(cnt){
r += 1;
if(s[r] == '[') cnt++;
else if(s[r] == ']') cnt--;
}
string tmp = decodeString(s.substr(l , r - l));
while(num--) ret += tmp;
i = r + 1;
}
}
return ret;
}
};
11.盛水最多的容器
class Solution {
public:
int maxArea(vector<int>& height) {
int ans = 0, i = 0, j = height.size() - 1;
while(i < j){
ans = max(ans, (j - i) * min(height[i], height[j]));
if(height[i] < height[j]) i++;
else j--;
}
return ans;
}
};
239. 滑动窗口最大值
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
if(k == 0) return ans;
deque<int> q;
int idx = 0;
while(idx < nums.size()){
if(!q.empty() && q.front() + k <= idx){
q.pop_front();
}
while(!q.empty() && nums[q.back()] < nums[idx]){
q.pop_back();
}
q.push_back(idx);
idx++;
if(idx >= k) ans.push_back(nums[q.front()]);
}
return ans;
}
};