算法!算法!算法!

原文地址:算法!算法!算法! 作者:jorchid

最近在复习算法,写点东西。

 

一、分治

什么是分治?嗯……4个人打牌,发现丢了一张牌,是哪张呢?如果你是这样解决的:把牌分成四份分别给四个人,每个人再按四种花色把分给自己的牌分好,大家一合计,就找到丢了哪张牌。是不是比一个人要快?这个差不多就有分治的味道了。

 

【题目1】单峰数组(<算法设计>)

 

一个数组中的数值随着下标的编号的增大,先增大后减小。如何求峰值数值的下标?

 

想想:

从第一个比到最后一个,把最大的记下来就可以了!复杂度O(n)

如果还要小一些的话,分治试试。从中间分,如果中间这个数比前面的数大,比后面的数小,那么在上坡。我们在它后面找~反之同理。如果中间这个数比它前面的和后面的数都大,那么太好了我们找到它了!

 

解:

对于数组为n的数组A[1..n],检查A[n/2].

如果A[n/2+1]>A[n/2]>A[n/2-1],那么在A[n/2+1]与A[n]之间进行同样的方法找峰值。

如果A[n/2+1]

如果A[n/2+1]>A[n/2]>A[n/2-1],那么A[n/2]是峰值。

 

复杂度:

递归方程:T(n)=T(n/2)+C

O(logn)

 

【题目2】一定赚钱的股票(《算法设计》)

如果你知道一支股票在n天里的所有价格,如何确定买入和卖出的时间,使自己一次买卖赚最多?

 

想想:

其实就是找到第i天和第j天,使得price(j)-price(i)最大。穷举所有的情况显然可以,代价O(n^2).可以分治吗?或者说,第n/2天时,你在做什么?1已卖出,2买入还未卖出,3未买入。为什么?因为1前n/2天买卖最赚,2前n/2天中某一天买入,后n/2天中某一天卖出最赚,3后n/2天买卖最赚。

 

解:

对于n天的价格:

递归计算出前n/2的最佳买卖时间,后n/2天的最佳买卖时间。还有前n/2天最便宜的一天和后n/2中最贵的一天。

解一定是三者中最优的那个。

 

复杂度:

T(n)=2T(n/2)+O(n)

T(n)=O(n*logn)

 

备注:有动态规划的O(n)的更优算法!

 

【题目3】数据库的中位数(《算法设计》)

两个大小为n的数据库,全部的2n个值均不同。

数据库的一个基本操作是“查询”,即输入k,返回一个第k个最小的值。

试图用最少的“查询”完成对两个数据库中位数的查找算法。

 

想想:

两个都可以找第k大,求全局的第n大。试着比较两个数据库的中位数,有什么发现吗?找个例子吧~

n=3,A={1,2,3},B={4,5,6}.比较发现B[2]=5>A[2]=2。那比B中比B[2]大的没希望是第n大了,因为那些数比B数组的一半都要大,而且也至少比A数组的一半都要大,已经比n个大了。同理,那些A中比A[2]小的也没希望了……这样一下少了一半,靠谱!

 

解:

比较两个数据库A,B中,中位数的大小。不妨假设A[n/2]>B[n/2].那么递归的寻找数据库A[1..n/2],B[n/2..n]的中位数。

 

复杂度:

T(n)=T(n/2)+c

T(n)=logn

 

【题目4】逆序对

数组a[1..n],有多少对(i,j),使得ia[j]?

想想:从中间开始拆?似乎是一个归并排序的附带产物?

解:

类似于归并算法。将a拆为A和B两个数组,递归计算A和B的逆序数,然后在合并的过程中计算A,B之间的逆序数。

计算A,B之间的逆序数:设A,B合并为数组C,那么在将A中一个元素添加到C末尾时,记录B中比这一元素小的元素数。

 

复杂度:

T(n)=2T(n/2)+O(n)

T(n)=nlog(n)

 

【题目5】重要逆序对

数组a[1..n],有多少对(i,j),使得i2a[j]?

想想:逆序对的加强版本!

解:

类似于归并算法。将a拆为A和B两个数组,递归计算A和B的逆序数,然后在合并的过程中计算A,B之间的重要逆序数。

复杂度:

T(n)=2T(n/2)+O(n)

T(n)=nlog(n)

 

【题目6】银行卡测试

有仪器可以检测两张银行卡是否使用同一个账号。

有n张银行卡,是否有n/2张以上是使用同一个账号?

 

想想:其实就是求众数。

 

解:

把卡分为n/2组,每组两张。如果两张卡使用同一个账号,那么标记一张;如果不是,则都两张卡标记。

重复此过程直到剩下的卡少于等于三张,逐一检查是否有n/2张以上是使用同一个账号。

 

复杂度:

T(n)=T(n/2)+O(n)

T(n)=O(n)

 

 

 

二、动态规划

举个例子:求10!,11!,12!。最好不要1个1个计算,否则很麻烦。可以先算出10!,然后再乘以11,得到11!,然后……这个就有动态规划的影子了~

【题目1】

一段长M的公路,用[0,M]来表示。如果放一块广告在xi,就得到收益ri,且任意广告距离大于5

例:{x1,x2,x3,x4}={6,7,12,14},{r1,r2,r3,r4}={5,6,5,1}最优解10

想想:!

解:

令profit (i)表示{x1,x2...xi}的最优解的收益。

那么profit(i)=max{profit(k)+ri,profit(i-1)}其中k满足x(k)

初始值profit(0)=0且profit(1)=r1,递归计算profit(2..n)

复杂度:

k的值的获取O(min(M,n)):若M较小可遍历,如果n比较小可以O(n)合并{xi-5}与{xi},使得在常数时间得到k。

循环为O(n)

综上为O(n)

 

【题目2】有n 项作业的集合J={1,2,…,n},每项作业i 有加工时间t(i) ∈Z+,效益值v(i),所有
任务必须在D∈Z+时刻结束,其中Z+表示正整数集合。
(1)一个可行调度是对J 的子集A 中任务的一个安排,对于i∈A,f(i)是开始时间,且
满足下述条件:
f(i)+t(i)≤f(j) 或者f(j)+t(j)≤f(i), j≠i i,j∈A
总时间不超过D。
设机器从 0 时刻开动,只要有作业就不闲置,求具有最大总效益的调度

 

解:

1.算法设计:使用贪心法,

 

 

 

三、回溯法

 

 

四、贪心法

 

 

五、np难的证明。

 

 

 

 

 

 

    

你可能感兴趣的:(算法)