CLRS 前几章

天又翻开CLRS,看了看前几章的习题,做了一些回顾,做一些笔记吧。

1.递归式求解常用的主方法

以b为base,取a的log,与变量f(n)进行比较,然后三种情况。

2. p23 2.3-6 在插入排序中加入二分检索

在Insertion-sort中前5-7行向A[1...j -1]寻找一个恰当的位置来放置A[j],在这个过程的同时,把每一个比A[j]大的元素向后移了一位,二分检索可以减少寻找位置的时间,但是不能减少移动元素所需要的时间,因此单独加入二分检索不能减少Insertion-sort所需要的时间。

3. p23 2.3-7 设计一个算法,在O(nlgn)以内判断给定集合S中有没有两个数的和为给定的X

①排序S,复杂度nlgn

②构造S’ = { z |  z =  X – y , y来自S

③排序S’,复杂度nlgn

④去掉S和S’中重复的元素,复杂度O(n)

⑤合并S和S’,如果合并数组有相同元素,那么存在a来自S和b来自S’使得 a + b = X

4. p23 2-1 在合并排序中加入插入排序

a> 每个子列表排序O(k^2),一共n/k个子列表,所以是O(nk)

b> 采用两两合并的策略pairwise,每一层合并O(n),一共有lg(n/k)层,所以可以满足要求

c>  k不能太大,最大来说应该是lgn

d> 在满足插入排序比归并快的情况下,k可以尽可能取大一些

5. p24 2-4 逆序对查找

这是一个很有趣的问题,之前在《入门经典》p144上看到过

c> 应该说每一次的while循环都在消除一个逆序对

算法代码(C),改进归并排序

求解逆序对:分治法

①分,求[1..k][k...n]的各自内部的逆序对

②求解跨越两个子数组的逆序对

③求和

具体程序修改合并排序中合并那一部分即可

5. p50 4-2 找出所缺的整数

A[1...n]只能按位访问,并且包含0到n的所有整数(缺一个),比如A[i]的第j位,如何在O(n)的时间内找到所缺的整数?

方法一:二分

1, 遍历整数0到n的第一位,分成两个数组:P1[1] 和P0[1],分别代表第一位是1,0的数,并记录第一位是1的个数CountN,代价为O(n)
2, 遍历数组A[1...n]的第一位, 分成两个组:Q1[1]和Q0[1],分别代表第一位是1,0的数,并记录1的个数CountA,代价为O(n)
3, 比较CountN和CountA的值,结果可能有两种情况CountN = CountA,或者CountN = CountA + 1, 前者表明所缺数的第一位为0, 后者为1,代价为O(1)
4, 通过3的结果,随后我们可以在P1[1]和Q1[1](CountN>CountA,即缺少第一位为1的数)  或者 P0[1]和Q0[1](CountN=CountA,即缺少第一位为0的数)中的第2位中重复步骤1,2中的操作,记录数组P1[2]、P0[2]和 CountN’及Q1[2]、Q0[2]和CountA’。代价为O(n/2)和O(n/2), 经过比较后可得到所缺数第二位是0还是1,决定接下来比较P1[2]和Q1[2]  或者 P0[2]和Q0[2],代价O(1)
5, 不断重复Ceiling(lg(n))次,最后即可找到所缺数总代价为2* (O(n) + O(n/2) + … +O(n/pow(2, k))) + … + O(1)) = 2* O(2n) = 4*O(n) = O(n)

方法二:

1到n所有数字加起来的和 减去 A[1]到A[n]的和

还有其它比较犀利的方法理解起来比较费劲,暂不考虑

6.堆(heap)保持堆的性质,需要lgn的复杂度,建立一个最大或者最小堆需要O(n)的时间,对于一个优先级队列

①返回最大值O(1)

②移除最大值O(lgn)

移除以后,用数组末尾的数据补到第一位,重新调整需要lgn

③更新某个i的键值key需要O(lgn)

④插入一个新的元素,需要O(lgn)

6. p82 6.5-8

将k个已排序链表合并,在O(nlgk)之内

方法:从k个链表中取出每个链表的头元素,建立一个大小为k的最小堆,将最小元素arr[0]移除,将arr[0]原来链表的后一个元素补到arr[0]位置上,调整堆,如果该链表已到末尾,将arr[k-1]放到arr[0],堆的大小减一(即移除之)

循环,复杂度为建堆 O(k) + 调整O(lgk) * n,满足题目要求、

7. p83 6-3

杨氏矩阵,还没有深入研究,挺有研究价值的,值得看看

posted on 2013-09-16 16:21  小书包_Ray  阅读(192)  评论(0编辑  收藏  举报

导航