高效算法设计针对ACM选手,我虽然不会打ACM了,但仍然要学习一下这部分内容。
渐进复杂度
分治法
划分问题:把问题的实例划分成子问题。
递归求解:递归解决子问题。
合并问题:合并子问题的解得到原问题的解。
排序与检索
归并排序
划分问题:把序列分成元素个数尽量相等的两半。
递归求解:把两半元素分别排序。
合并问题:把两个有序表合并成一个。
合并过程:每次只需要把两个序列的最小元素加以比较,删除其中的较小元素并加入合并后 的新表即可。
快速排序
划分问题:把数组的各个元素重排后分成左右两部分,使得左边的任意元素都小于或 等于右边的任意元素。
递归求解:把左右两部分分别排序。
合并问题:不用合并,因为此时数组已经完全有序。
二分查找
在有序表中查找元素常常使用二分查找(Binary Search),有时也译为“折半查找”,基 本思路就像是“猜数字游戏”:你在心里想一个不超过1000的正整数,我可以保证在10次之内 猜到它——只要你每次告诉我猜的数比你想的大一些、小一些,或者正好猜中。
递归与分治
棋盘覆盖
题目
分析
2x2的方格,自成一个L
更大的方格2k x 2k,总可以分割成更小的方格,对另外三块不带黑格的,将对角线三个用L型占据,相当于每个大方格都有黑格子,一直递归到2x2为止
循环日程表
巨人与鬼
贪心法
背包问题
题目
最优装载问题。给出n个物体,第i个物体重量为wi。选择尽量多的物体,使得总重量不超过C。
分析
由于只关心物体的数量,所以装重的没有装轻的划算。只需把所有物体按重量从小到大排序,依次选择每个物体,直到装不下为止。这是一种典型的贪心算法,它只顾眼前,但却 能得到最优解。
题目
部分背包问题。有n个物体,第i个物体的重量为wi,价值为vi。在总重量不超过C的情 况下让总价值尽量高。每一个物体都可以只取走一部分,价值和重量按比例计算。
分析
本题在上一题的基础上增加了价值,所以不能简单地像上题那样先拿轻的(轻的可能价 值也小),也不能先拿价值大的(可能它特别重),而应该综合考虑两个因素。一种直观的 贪心策略是:优先拿“价值除以重量的值”最大的,直到重量和正好为C。
区间相关问题
题目
**选择不相交区间。**数轴上有n个开区间(ai, bi)。选择尽量多个区间,使得这些区间两两 没有公共点。
分析
首先明确一个问题:假设有两个区间x,y,区间x完全包含y。那么,选x是不划算的,因 为x和y最多只能选一个,选x还不如选y,这样不仅区间数目不会减少,而且给其他区间留出 了更多的位置。接下来,按照bi从小到大的顺序给区间排序。贪心策略是:一定要选第一个区间。
题目
区间选点问题。数轴上有n个闭区间[ai, bi]。取尽量少的点,使得每个区间内都至少有 一个点(不同区间内含的点可以是同一个)。
分析
把所有区间按b从小到大排序(b相同时a从大到小排序),则如果出现区间包含的情况,小区间一定排在前面。第一个区间应该取哪一个点呢?此处的贪心策略是:取最后一个点。