算法导论----VLSI芯片测试; n个手机中过半是好的,找出哪些是好手机
对于分治(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
题目要求给出一个线性的算法。如果对主定理(算法导论)非常熟悉,可以大胆猜测可能是如下的递归式:
T(n)<=T(n/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个手机中过半是好的,找出哪些是好手机的更多相关文章
- 算法导论 (Thomas H.Cormen / Charles E.Leiserson / Ronald L.Rivest / Clifford Stein 著)
第一部分 基础知识 第1章 算法在计算中的作用 第2章 算法基础 第3章 函数的增长 第4章 分治策略 第5章 概率分析和随机算法 第二部分 排序和顺序统计量 第6章 堆排序 第7章 快速排序 第8章 ...
- 堆排序与优先队列——算法导论(7)
1. 预备知识 (1) 基本概念 如图,(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树.树中的每一个结点对应数组中的一个元素.除了最底层外,该树是完全充满的,而且从左向右填充.堆的数组 ...
- 最大子段和的DP算法设计及其效率测试
表情包形象取自番剧<猫咪日常> 那我也整一个 曾几何时,笔者是个对算法这个概念漠不关心的人,由衷地感觉它就是一种和奥数一样华而不实的存在,即便不使用任何算法的思想我一样能写出能跑的程序 直 ...
- 《算法导论》——矩阵乘法的Strassen算法
前言: 很多朋友看到我写的<算法导论>系列,可能会觉得云里雾里,不知所云.这里我再次说明,本系列博文时配合<算法导论>一书,给出该书涉及的算法的c++实现.请结合<算法导 ...
- 《算法导论》——MergeSort
前言: 在今后的日子里,我将持续更新博客,讨论<算法导论>一书中的提到的各算法的C++实现.初来乍到,请多指教. 今日主题: 今天讨论<算法导论>第二章算法基础中的归并排序算法 ...
- Demo003 最大连续子数组问题(《算法导论》4.1-5)
问题 问题描述 给定n个整数(可能为负数)组成的数组,要求一个数组连续下标和的最大值,数组的元素可正.可负.可为零. 数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和.求所有子数组的 ...
- 【算法导论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 ...
- 【算法导论C++代码】归并排序
一个归并排序卡了一天最后还是归并算法有问题,最初是为了把算法导论的伪代码转到c++而加了一些东西,其中在对左右数组的赋值那里出了问题.因为进行测试时不完全,就是只用书上的数组进行测试时,归并算法部分还 ...
- 《算法导论》 — Chapter 8 线性时间排序
序 到目前为止,关于排序的问题,前面已经介绍了很多,从插入排序.合并排序.堆排序以及快速排序,每一种都有其适用的情况,在时间和空间复杂度上各有优势.它们都有一个相同的特点,以上所有排序的结果序列,各个 ...
随机推荐
- Mybatis 学习-1
本次MyBatis基础实例教程主要讲述MyBatis在项目中的配置方法,实体对象的关系映射.关联关系,以及如何实现一个BaseDao的功能 实例数据库的表结构 CREATE TABLE `blog_u ...
- PHP Warning: ob_start() : output handler 'ob_gzhandler conflicts with 'zlib output compression'
安装phpcms过程中,会遇到Warning: ob_start() : output handler 'ob_gzhandler conflicts with 'zlib output compr ...
- Pinyin4Net
.net使用的汉字转拼音库.Pinyin4Net 是直接从 Pinyin4J 翻译过来的,很多代码甚至是直接copy的. 用法与pinyin4j完全相同,具体请查阅pinyin4j文档. —— 查看更 ...
- WebDataTree 使用XML做数据源绑定数据
英文版原文链接:http://www.infragistics.com/help/topic/e5f07b51-ee2d-4a33-aaac-2f43cffff327 所使用的控件版本为:Infrag ...
- SQL数据库第一部分
数据库:程序用来存取数据的 ACCESS:自带,比较小,不是很专业 SQL Server:主要用在.NET语言中,比较专业.微软开发 MYSQL:主要用在PHP语言中,比SQL server体积比较小 ...
- AngularJS理论基础
AngularJS理论基础 AngularJs是一个用于设计动态web应用的结构框架. 它是一个框架,不是类库,是像EXT一样提供一整套方案用于设计web应用.它不仅仅是一个javascript框架, ...
- 函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。
在dllimport中加入CallingConvention参数就行了,[DllImport(PCAP_DLL, CharSet = CharSet.Auto, CallingConvention = ...
- JS比较好用的一些方法搜集
JS比较好用的一些方法搜集 Math.ceil(x) -- 返回大于等于数字参数的最小整数(取整函数),对数字进行上舍入 Math.floor(x)--返回小于等于数字参数的最大整数,对数字进行下舍入 ...
- SASS学习笔记1 —— 安装、编译和调试
一.什么是SASS SASS是一种"CSS预处理器"(css preprocessor)的开发工具,为CSS加入编程元素,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的 ...
- 分形树Fractal tree介绍——具体如何结合TokuDB还没有太懂,先记住其和LSM都是一样的适合写密集
在目前的Mysql数据库中,使用最广泛的是innodb存储引擎.innodb确实是个很不错的存储引擎,就连高性能Mysql里都说了,如果不是有什么很特别的要求,innodb就是最好的选择.当然,这偏文 ...