https://www.acwing.com/blog/content/277/
排序
快排、归并排序
- 模板背会。
- 模板题目默写一遍。
- 提高熟练度。同一个模板题重复3-5次?
快排——分治
- 确定分界点x:取左边界 q[l], 中间值 q[(l+r)/ 2], q[r], 随机
- 调整区间。使第一个区间的数都小于等于x。第二个区间都大于等于x。(难点)
- 递归处理左右两段
调整区间方法(最简单):
- 开两个新数组a、b。
- 扫描数组所有数。如果小于等于x则插入a
- 否则插入b
- 在把a、b放回原来数组
这样需要额外空间。
优美的方法:
- 两个指针i,j,指向两端。
- a[i]只要小于等于x就继续往右走
- a[j]只要大于等于x就继续向左走
- 如果此时 i<j, 就交换a[i], a[j]
归并排序——分治
- 确定分界点:mid=(l + r) / 2
- 递归排序left、right
- 归并left、right。合二为一(难点) 双指针算法
二分
整数二分
边界比较多。容易死循环。有单调性肯定可以二分。没有单调性也可以二分。本质:一半区间满足某个性质。另一半区间不满足性质。可以找到两个区间的分界点。
- 二分红色中间点
- mid=(l+r + 1) / 2; (注意这里加了 1 )
- if(check(mid))
- 成立:mid在红色区间,则红色分界点在[mid, r]里面。是包含mid的。l=mid
- 不成立:mid在绿色区间。红色分界点一定在[l, mid - 1]。是不包含mid的。r=mid-1
- 二分绿色分界点
- mid=(l+r) / 2(注意这里没有加1)
- if(check(mid))
- true, mid在绿色区间内。绿色边界点在[l, mid]上。r = mid。
- false,mid在红色区间内。绿色分界点在[mid + 1, r]内,l=mid+1。
- 如何确定怎么二分?
- 先写check。看怎么更新区间。如果是l=mid,要补上+1。如果是r=mid。则不用加一
- 加1是因为除法是下取整的。偏向 l 一侧。所以l=mid如果不加一。区间就缩小不了。就死循环了。