算法基础课
第一章 基础算法(一)
1.快速排序——分治[O(n logn)]
①确定分界点:q[l]、q[(l+r)/2]、q[r] 、随机
②调整区间,小于x的放在x左端(无序),大于的放在右边(无序),等于左右都可
③递归处理左右两端(重复1 2,对左右两端各自继续分治)
模板:
cpp(785):
#include<iostream> using namespace std; const int N = 1e6 + 10; int n; int q[N]; void quick_sort(int q[], int l, int r) { if (l >= r) return; int x = q[l], i = l - 1, j = r + 1; while (i < j) { do i++; while (q[i] < x); do j--; while (q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l ,j); quick_sort(q, j+1, r); } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &q[i]); quick_sort(q, 0, n-1); for (int i = 0; i < n; i++) printf("%d", q[i]); return 0; }
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RHpbfIA0-1679153945958)(D:\照片\typora笔记\算法基础课\快速排序.png)]
2.归并排序[O(n logn)]
①确定分界点 mid = ( l + r ) / 2
②递归排序
③归并——合二为一
模板(787):
#include <iostream> using namespace std; const int N = 1e5 + 10; int a[N], tmp[N]; void merge_sort(int q[], int l, int r) { if (l >= r) return; int mid = l + r >> 1; merge_sort(q, l, mid), merge_sort(q, mid + 1, r); int k = 0, i = l, j = mid + 1; while (i <= mid && j <= r) if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ]; else tmp[k ++ ] = q[j ++ ]; while (i <= mid) tmp[k ++ ] = q[i ++ ]; while (j <= r) tmp[k ++ ] = q[j ++ ]; for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j]; } int main() { int n; scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); merge_sort(a, 0, n - 1); for (int i = 0; i < n; i ++ ) printf("%d ", a[i]); return 0; }
3.二分查找
关于二分模板问题
1)
一个mid = (l+r)>>1
一个mid = (l+r+1)>>1
加不加1 完全取决于 l = mid 还是r = mid
l等于mid时必须+1向上取整 不然会陷入l=l的死循环
r = mid 时候不用加1 因为下一步l = r 直接会退出循环
2)
这两个模板解决的是 找>=||<=||>||< 某个数的
最左或最右的位置 但这个数不一定在二分的数组中
如果在就能准确找到
如果不在 找到的就是最接近答案的数(你要找大于等于5的第一个数)但
数组中没有5 那找到的就是6的位置(如果有6的话)
所以二分是一定有答案的
我觉得这个二分模板就是解决了我上面说的(>=||<=||>||< )这四种情况
模板(789):
#include <iostream> using namespace std; const int N = 100010; int n, m; int q[N]; int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) scanf("%d", &q[i]); while (m--) { int x; scanf("%d", &x); int l = 0,r = n - 1; while (l < r) { int mid = l + r >> 1; if (q[mid] >= x) r = mid; else l = mid + 1; } if (q[l] != x) cout << "-1 -1" << endl; else { cout << l << ' '; int l = 0, r = n - 1; while (l < r) { int mid = l + r + 1 >> 1; if (q[mid] <= x) l = mid; else r = mid - 1; } cout << l << endl; } } return 0; }
浮点(790):
#include<iostream> using namespace std; int main() { double x; cin >> x; double l = -100, r = 100; while (r - l > 1e-8) { double mid = (l + r) / 2; if (mid * mid * mid >= x) r = mid; else l = mid; } printf("%.6lf\n", l); return 0; }
l > 1e-8) { double mid = (l + r) / 2; if (mid * mid * mid >= x) r = mid; else l = mid; }
printf("%.6lf\n", l); return 0; }