对于分治(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

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

  1. 算法导论 (Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein 著)

    第一部分 基础知识 第1章 算法在计算中的作用 第2章 算法基础 第3章 函数的增长 第4章 分治策略 第5章 概率分析和随机算法 第二部分 排序和顺序统计量 第6章 堆排序 第7章 快速排序 第8章 ...

  2. 堆排序与优先队列——算法导论(7)

    1. 预备知识 (1) 基本概念     如图,(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组 ...

  3. 最大子段和的DP算法设计及其效率测试

    表情包形象取自番剧<猫咪日常> 那我也整一个 曾几何时,笔者是个对算法这个概念漠不关心的人,由衷地感觉它就是一种和奥数一样华而不实的存在,即便不使用任何算法的思想我一样能写出能跑的程序 直 ...

  4. 《算法导论》——矩阵乘法的Strassen算法

    前言: 很多朋友看到我写的<算法导论>系列,可能会觉得云里雾里,不知所云.这里我再次说明,本系列博文时配合<算法导论>一书,给出该书涉及的算法的c++实现.请结合<算法导 ...

  5. 《算法导论》——MergeSort

    前言: 在今后的日子里,我将持续更新博客,讨论<算法导论>一书中的提到的各算法的C++实现.初来乍到,请多指教. 今日主题: 今天讨论<算法导论>第二章算法基础中的归并排序算法 ...

  6. Demo003 最大连续子数组问题(《算法导论》4.1-5)

    问题 问题描述  给定n个整数(可能为负数)组成的数组,要求一个数组连续下标和的最大值,数组的元素可正.可负.可为零.  数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的 ...

  7. 【算法导论C++代码】Strassen算法

    简单方阵矩乘法 SQUARE-MATRIX-MULTIPLY(A,B) n = A.rows let C be a new n*n natrix to n to n cij = to n cij=ci ...

  8. 【算法导论C++代码】归并排序

    一个归并排序卡了一天最后还是归并算法有问题,最初是为了把算法导论的伪代码转到c++而加了一些东西,其中在对左右数组的赋值那里出了问题.因为进行测试时不完全,就是只用书上的数组进行测试时,归并算法部分还 ...

  9. 《算法导论》 — Chapter 8 线性时间排序

    序 到目前为止,关于排序的问题,前面已经介绍了很多,从插入排序.合并排序.堆排序以及快速排序,每一种都有其适用的情况,在时间和空间复杂度上各有优势.它们都有一个相同的特点,以上所有排序的结果序列,各个 ...

随机推荐

  1. robotframework笔记18

    测试执行 如何创建测试套件结构解析 执行测试数据,如何继续执行一个测试用例失败后, 以及如何优雅地停止整个测试执行. 执行流 执行测试套件和 总是在一个测试套件执行测试用例. 一个测试套件 创建从一个 ...

  2. [redis] 征服Redis系列

    征服 Redis:简介+安装+调优+测试+主从+集群 征服 Redis + Jedis:简单Jedis+池化Jedis+集群Jedis 征服 Redis + Jedis + Spring (一)—— ...

  3. Intellij IDEA 安装 Mybatis插件

    1.Ctrl+Alt+s

  4. html5的标签

    1.article与section div的区别 当一个标签只是为了样式化或者方便脚本使用时,应该使用 div . section 表示一段专题性的内容,一般会带有标题.,section 应用的典型场 ...

  5. 转:Struts2<s:iterator value="" var="lst">中var的使用和一些标签的使用体会

    比如<s:iterator value="pmOperateList" var="lst"> <!-- iterator加上var 等价于重新 ...

  6. Collecting Bugs(POJ 2096)

    Collecting Bugs Time Limit: 10000MS   Memory Limit: 64000K Total Submissions: 3064   Accepted: 1505 ...

  7. 开源软件架构总结之——Bash(readline做输入交互式,词法语法分析,进程交互)

    第3章 The Bourne-Again Shell Bash的主要组件:输入处理,解析,单词展开(word expansion)和其他命令处理,管道(pipeline)中的命令执行.这些组件构成一个 ...

  8. Spark(2) - Developing Application with Spark

    Exploring the Spark shell Spark comes bundled with a PERL shell, which is a wrapper around the Scala ...

  9. ruby开源项目之Octopress:像黑客一样写博客(zhuan)

    ruby开源项目之Octopress:像黑客一样写博客 百度权重查询 词库网 网站监控 服务器监控 SEO监控 Swift编程语言教程 今年一直推荐的一种写作方式.markdown语法快速成文,git ...

  10. ComboBox绑定

    this.ComboBox1.AutoCompleteMode = AutoCompleteMode.SuggestAppend; this.ComboBox1.AutoCompleteSource ...