算法导论----VLSI芯片测试; n个手机中过半是好的,找出哪些是好手机

时间:2023-02-27 11:38:38

对于分治(Divide and Conquer)的题目,最重要是

1.如何将原问题分解为若干个子问题,

2.子问题中是所有的都需要求解,还是选择一部分子问题即可。

还有一点其实非常关键,但是往往会被忽视:分解后的子问题除了规模较原问题小之外,必须和原问题具有相同的性质。

在子问题的划分时,只有这一点保证,才能递归求解子问题,从而得到solution。

下面通过几个例子,详细地介绍下这个思路。

题目一:

You have n mobile phones and a contraption that holds two phones at the

same time and allows them to test each other. Once you load the phones into

the contraption, they test each other and each outputs whether the other

one is good or bad. If a phone is actually good than it will always output a

correct result. Unfortunately, if it is bad, its reply is unrelated to the real

state of the other phone and hence cannot be trusted. In other words, the

badphone can each time output whatever it wants. [For all practical pur-

poses,you can assume that the bad phone always outputs something that

willbe as unhelpful to you as possible.] Loading two phones and letting

them test each other will be called a test. We have 4 cases that might result

from a single test:

Chip A says

Chip B says

Conclusion

B is good

A is good

Either good or bad

B is good

A is bad

At least one is bad

B is bad

A is good

At least one is bad

B is bad

A is bad

At least one is bad

We will assume that there are more than n /2 good phones. Final goal is

to identify all the good and all the bad phones. In the question we are

after a deterministic algorithm, i.e. you cannot make use of any type of

randomization.

1.Explain how to find a single good phone. [Hint: Start by explaining

how to use O(n) tests to reduce the problem size by a constant factor.]

2.Use the previous part to show how to identify all of the good phones

by performing Θ(n) tests.

这个题目其实就是算法导论的一题课后题: VLSI芯片测试

思路: 目标是从n个手机中找到一个good phone.

注意题目给出了一个条件,原问题中超过一半的手机是好的。如果用分治,子问题必须同样满足good phones超过半数这一个性质。

算法1:

先利用超过半数手机是好的这一性质,构造一个O(n^2)的算法。

Consider a phone x, 拿它与所有的phones做tests:

if超过半数的手机说它是good, then it's good.

Else it's bad.

打个比喻,法院审判一个犯人,陪审团中超过半数的人是公正的(如果 x is good, 他们一定投反对票),其余的人随便瞎给判决。无论其余的人怎么投票,根据少数服从多数的原则,最终犯人是否无罪释放取决于那超半数的公正的陪审团成员的判决。

注意: 一个重要的细节问题

总共n部手机,拿出一个手机后,剩余n-1部手机, 这n-1个手机中还是超半数是好手机吗??(如果不是,算法1不再work)

答案是肯定的!!! 题目要求n是偶数n中good phones > bad phones,

                                    因此, n个手机中 good phones 至少比 bad phones多 2个 (反证法,若只好手机比坏手机多1个,则n是奇数,矛盾)

所以n个手机任意去掉一个手机后,仍然满足超半数是好手机的性质。

算法2:

Divide and Conquer

题目要求给出一个线性的算法。如果对主定理(算法导论)非常熟悉,可以大胆猜测可能是如下的递归式:

Tn<=Tn/2)+
O(n);

可证明T(n)=O(n)

1》给个直观的例子:

自从看到
An apple a day, keep doctors away, 这句谚语,每天我都会吃苹果。

但我吃苹果的方式很特殊,先吃半个,再吃剩下的半个的一半,再吃剩下的半个的一半。。。。

结论: 我永远都吃不完这一个苹果。。。。(It's a joke.)

其实这个例子就给出了T(n)的上界是O(n):

每次我吃掉的一半就是O(n),剩下T(n/2),上界就是我最初的一个苹果也就是O(n)

2》主定理(算法导论):

满足条件3

3》纯数学推导

T(n)<= n + n/2 + n/4 +...+1 = 2n – 2 = O(n)

我们的目标就是:在O(n)时间内,从原问题(规模是n)中找到一个子问题(规模小于n/2),并对其求解。

注意:子问题必须满足超过半数手机是 good。

第一步: 考虑规模要少于一半

咋办?

首先,直观想法:对半开,假设n是偶数,两两结对,做test

测试结果有4个 cases: (好-好),(好-坏),(坏-好),(坏-坏)

注意到后三种情况,至少有一个是坏的phone(用反证法非常容易证明)

但是同时还要满足 超半数是good:

选择留下少于一半的元素(超半数是good)的,

或者说,选择丢掉超过半数的元素(超半数是bad)的。

Bingo!:丢掉测试结果是(好-坏,坏-好,坏-坏)(超半数是bad的)的phones,剩下的元素就是超半数是好的。

但是不要高兴得太早,子问题还有一个性质:《规模》

(好-好)的规模还一定是少于半数的,还得从其中丢掉一部分元素!!!

但是(好-好)只能保证 both good or both bad.

遇到了个小问题,不用怕,要相信自己的思路是对的。

(好-好)的所有元素中去掉一半元素,规模不就满足<n/2

但是如何剔除呢??

第一种思路,选择一半的(好-好)对去掉,不对。不能保证超半数是good的性质了;

第二种思路, 每一组(好-好)对中选择一个元素。Bingo!由于要么bothgood,
or both bad, 这样做一定能保证,剩余的元素中good> bad;

(还有一点需要证明,(好-好)对一定会出现吗?反证法:若不存在,其余三种情况都是至少有一个是坏的,因此超半数是bad,矛盾)

Complexity:每次两两结对做tests,耗时O(n)


T(n)<= T(n/2) +O(n)所以复杂度是线性。

总结:

分治的子问题必须和原问题具有相同的性质。

练习:n个硬币,其中有两个硬币分别重m+1, m-1克,其余都重m克,O(lgn)时间找出两枚假币

http://blog.csdn.net/shoulinjun/article/details/17188431