一、基础算法
包括排序、二分、高精度、前缀和与差分、双指针算法、位运算、离散化、区间合并等内容。
Quick_sort
①确定分界点,取左边界q[l]或右边界q[r]或中间点q[(l+r)/2]或随机一点。
②调整区间,x(分界点)左边的数都小于x,右边的数都大于x。(核心步骤)
③递归处理左右两段。
平均时间复杂度:nlogn
最坏时间复杂度:n^2
例题:785. 快速排序 、786. 第k个数
1 2 3 4 5 6 7 8 9 10 11 12 13
| void quick_sort(int q[], int l, int r){ if(l>=r) return; int i = l-1, j = r+1, x = q[l+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); }
|
归并排序——分而治之
①确定分界点:mid =(l+r)/2
②递归排序左半边和右半边
③归并–合二为一(核心步骤)
平均时间复杂度:nlogn
例题:787. 归并排序、788. 逆序对的数量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| void merge_sort(int p[], l, r){ if(l>=r) return; int mid = l+r>>1; merge_sort(p, l, mid); merge_sort(p, mid+1, r); int tmp[N]; int k = 0, i = 1, 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]; }
|
整数二分
例题:789. 数的范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| bool check(int x) {}
int bsearch_1(int l, int r){ while(l < r){ int mid = l+r>>1; if(check(mid)) r = mid; else l = mid + 1; } return l; }
int bsearch_2(int l,int r){ while(l<r){ int mid = l + r + 1 >> 1; if(check(mid)) l = mid; else r = mid - 1; } return l; }
|
高精度加法
例题: 791. 高精度加法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
vector<int> add(vector<int> &A, vecotr<int> &B){ if(A.size() < B.size()) return add(B, A); vector<int> C; int t = 0; for(int i=0;i<A.size();i++){ t += A[i]; if(i<B.size()) t += B[i]; C.push_back(t%10); t /= 10; } if(t) C.push_back(t); return C; }
|
高精度减法
例题:792.高精度减法
1 2 3 4 5 6 7 8 9 10 11 12 13
| vector<int> sub(vector<int> &A,vecotr<int> &B){ vector<int> C; for(int i = 0, t = 0;i < A.size(); i++){ t = A[i] - t; if(i<B.size()) t -= B[i]; C.push_back((t+10)%10); if(t<0) t = 1; else t = 0; } while(C.size()>1 && C.back()==0) c.pop_back(); return C; }
|
高精度乘低精度
例题:793. 高精度乘法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| vector<int> mul(vector<int> &A, int b){ vector<int> C; int t = 0; for(int i=0;i<A.size()||t;i++){ if(i<A.size()) t += A[i] * b; C.push_back(t%10); t /= 10; } while(C.size() > 1 && C.back() == 0) C.pop_back(); return C; return C; }
|
高精度除以低精度
例题:794. 高精度除法
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| // C = A / b ... r , A >= 0 , b > 0 vector<int> div (vector<int> &A, vecotr<int> &b, r){ vector<int> C; r = 0; for(int i= i.size() - 1; i >= 0; i--){ r = r * 10 + A[i]; C.push_back(r/b); r %= b; } reverse(C.begin(), C.end()); while(C.size() > 1 && C.back() == 0) C.pop_back(); //去除前导0 return C; }
|
一维前缀和
例题:795. 前缀和
1 2
| s[i] = a[1] + a[2] + ... + a[i] a[l] + ... a[r] = s[r] - s[l - 1]
|
二维前缀和
例题:796. 子矩阵的和
1 2 3
| s[i, j] = 第i行j列格子左上部分所有元素的和 以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为: s[x2, y2] - s[x1 - 1, y2] - s[x2, y1-1] + s[x1 -1, y1 - 1]
|
一维差分
例题:797. 差分
1
| 给区间[l ,r]中的每个数加上c:B[l] += c, B[r + 1] += c
|
二维差分
例题:798. 差分矩阵
1 2
| 给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中所有的元素加上C: s[x1, y1] += c, s[x2 + 1, y1] -= c, s[x1, y2 + 1] -= c, s[x2 + 1, y2 + 1] += c
|
位运算
例题:801. 二进制中1的个数
1 2
| 求n的第k位数字:n >> k & 1 返回n的最后一位1:lowbit(n) = n & -n
|