804 字
4 分钟
竞赛算法(2) 排序, 二分
快速排序
基于分治思想, 对于每个区间将其分为较小的一段和较大的一段, 较小段的最大值小于等于较大段的最小值.
快速排序的步骤
- 选定基准值x, 将某个区间分为小于等于x的部分和大于x的部分, 当x靠近中位数时分治效果较为理想. 通常随机选取区间中的某个数.
- 使用双指针i, j. 其中i从前往后遍历, j从后往前遍历.
- 保证i遍历过的部分都是小于等于x的, j遍历过的都是大于x的.
- 如果i处大于x, j处小于等于x, 并且i在j前面, 交换两处的数字, 并移动i和j
- 如果i不在j前面, 说明已经遍历完毕, break.
- 递归处理左右两段.
void qks(vector<int>& arr, int l, int r) { if (l >= r) return; int x = arr[(l + r) / 2]; int i = l - 1; int j = r + 1; while (i < j) { do i++; while (arr[i] < x); do j--; while (arr[j] > x); if (i < j) swap(arr[i], arr[j]); } qks(arr, l, j); qks(arr, j + 1, r);}归并排序
同样基于分治思想, 见算法导论.
void mgs(vector<int>& arr, int l, int r) { static vector<int> tmp(arr.size()); if (l >= r) return;
int mid = (l + r) / 2; mgs(arr, l, mid), mgs(arr, mid + 1, r);
int i = l, j = mid + 1, k = 0; while (i <= mid && j <= r) { if (arr[i] <= arr[j]) { tmp[k++] = arr[i++]; } else { tmp[k++] = arr[j++]; } } while (i <= mid) { tmp[k++] = arr[i++]; } while (j <= r) { tmp[k++] = arr[j++]; }
for (i = l, k = 0; i <= r; i++, k++) { arr[i] = tmp[k]; }}归并排序用于求逆序对
long long ans = 0;void mgs(vector<int>& arr, int l, int r) { static vector<int> tmp(arr.size()); if (l >= r) return;
int mid = (l + r) / 2; mgs(arr, l, mid), mgs(arr, mid + 1, r);
int i = l, j = mid + 1, k = 0; while (i <= mid && j <= r) { if (arr[i] <= arr[j]) { // 注意这里必须是小于等于 tmp[k++] = arr[i++]; } else { tmp[k++] = arr[j++]; ans += mid - i + 1; // 添加的一行 } } while (i <= mid) { tmp[k++] = arr[i++]; } while (j <= r) { tmp[k++] = arr[j++]; }
for (i = l, k = 0; i <= r; i++, k++) { arr[i] = tmp[k]; }}二分查找
bool check(int a);void bs(const vector<int>& arr) { int n = arr.size(); int l = -1; int r = n; while (r - l > 1) { int mid = (l + r) / 2; if (check(arr[mid])) { l = mid; } else { r = mid; } } return;}// 实数域二分const double PCS = 1e-7;bool check(double a);double bs(double n, double l, double r) { while (r - l > PCS) { double mid = (l + r) / 2; if (check(mid)) { l = mid; } else { r = mid; } } return l;}主定理(master公式)
用于求解分治算法的时间复杂度.
若
我们去比较与, 分为如下几种情况:
- 若, 则时间复杂度由递归主导,
- 若, 则时间复杂度由递归部分与非递归部分共同影响, . 需要注意不算阶数.
- 若, 同时满足正则条件(通常竞赛题目都满足), 则时间复杂度由非递归主导,
竞赛算法(2) 排序, 二分
https://fuwari.vercel.app/posts/竞赛算法2-排序/