对于分治(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. KVC与KVO的进阶使用

    本篇主要介绍键-值编码KVC,键值观察KVO的进阶使用的一些技巧主要是一下两个方面: KVC的集合操作符 KVO的手动实现方式 KVC集合操作符 关于集合操作符在苹果官方文档搜索Collection ...

  2. hdu----(1402)A * B Problem Plus(FFT模板)

    A * B Problem Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  3. 整理的一些模版LCS(连续和非连续)

    对于连续的最大串,我们称之为子串....非连续的称之为公共序列.. 代码: 非连续连续 int LCS(char a[],char b[],char sav[]){ int lena=strlen(a ...

  4. Unique Paths [LeetCode]

    A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...

  5. 在列表页,按照指定的category取所属的post列表

    在某些指定的页面,例如news,blog等页面,需要列出指定某种类型的文章列表,这种情况下,可以先添加两个category,分别命名news,blog,然后再分别添加几个post,指定每个post所属 ...

  6. C#与Java中相等关系

    最近在学习java的语法,发现java中两个字符串某些情况下不能用==这个来判断,比如自己定义的类中有String属性,那么就不能用==判断两个是否相等.这才开始比较C#和Java在这里的区别,最后发 ...

  7. 通过计算机名访问linux

    1.安装samba 2.设置/etc/samba/smb.conf的 netbois name 配置节的值为你要设置的名称,如 netbois name = mylinux 也可以不设置此项,如果不设 ...

  8. 源代码解读Cas实现单点登出(single sign out)功能实现原理

    关于Cas实现单点登入(single sing on)功能的文章在网上介绍的比较多,想必大家多多少少都已经有所了解,在此就不再做具体介绍.如果不清楚的,那只能等我把single sign on这块整理 ...

  9. [Js]焦点图轮播效果

    一.所用到的知识点 1.DOM操作 2.定时器 3.事件运用 4.Js动画 5.函数递归 6.无限滚动大法 二.结构和样式 <div id="banner" class=&q ...

  10. 动态链接库dll键盘钩子后台记录代码示例

    //.header #ifndef _DLLHOOK_H_ #define _DLLHOOK_H_ #include <windows.h> #define DLL_EXPORT_FUN ...