算法题----称硬币: 2n(并不要求n是2的幂次方)个硬币,有两个硬币重量为m+1, m-1, 其余都是m 分治 O(lgn)找出假币
Description:
有2n个硬币和一个天平,其中有一个质量是m+1, 另一个硬币质量为m-1, 其余的硬币质量都是m。
要求:O(lgn)时间找出两枚假币
注意: n不一定是2的幂次方
算法1:O(n)算法
将2n个硬币分成n组(每组2个)进行称量:
结果只有两种: 1. 仅有一组出现天平不平衡: 一定就是 两个假币
2. 出现两组天平不平衡: 这四个硬币中必定存在两个假币。将重的硬币称量,轻的两个硬币称量得到结果。
算法2: O(lgn)算法 分治
首先假设n是2的幂次方(如果不是,则可以加入新的真币,使得硬币数目是2的幂次方)
第一步: 对所有的硬币编号, 从0到2n-1
第二步: 由于2n是2的幂次方,假设2n的二进制表示有lgn位
for i=0, lgn;
根据二进制表示第i位是否为0,或1
将 2n个硬币分成两个数目为n的集合,放到天平的两边;
if 天平不平衡, break;
end for;
注意: 由于两个假币的编号不同,所以它们的二进制表示必定某一位不同,不妨设为第k位
第三步: 我们得到了两堆数目都是n的硬币集合, 注意此时两个假币已经分开
用O(lgn)的分治算法在两堆硬币中分别求出假币
如果n不是2的幂次方,注入真币,使得数目为2的幂次方。
下面证明注入的真币数目一定不超过2n
假设 2^k < 2n < 2^(k+1)
加入的真币数目= 2^(k+1) - 2n < 2^(k+1) - 2^k = 2^k < 2n
结论, 加入硬币后,总硬币数不超过4n,所以复杂度仍旧是O(lgn)
算法三: 并不需要通过加硬币, 也能O(lgn)找出假币
n不是2的幂次方的问题在于: 根据2进制数某一位1,0分成2堆硬币,可能出现数目不等的情况。
第1位: 该二进制位为1的堆 和 为0的堆 数目至多相差1(编号是奇数和偶数的硬币数至多相差1个)
做法: 从多的那堆中 丢掉 编号最大的硬币!!!
1. 因为丢了以后,
天平若平衡:则丢掉的一定是真币。
反之,则不能确定。
这样最终我们得到3堆硬币,两堆就是天平上不平衡的两堆,第三堆就是算法过程中被我们丢掉的一堆。两枚假币必定在三堆硬币中,而且已经被分开。O(lgn)找出3堆硬币中各自的假币(注意,虽然有一堆没有假币,但是算法还是会得到一个结果,当然它是真币)。
然后 3枚硬币天平称两次,最重的和最轻的就是假币
2. 为什么丢编号最大的硬币呢? 其实为了保证下一步时 两堆硬币数同样具有最多相差1的性质
因此,可以像算法2一样,用 O(lgn)时间把 两枚假币 分开。。再用O(lgn)找出假币即可。。。
PS: 多谢女朋友的指点,忽然想到这个算法原来可以不用“加硬币”的方法,也可解决。。
算法题----称硬币: 2n(并不要求n是2的幂次方)个硬币,有两个硬币重量为m+1, m-1, 其余都是m 分治 O(lgn)找出假币的更多相关文章
- 笔试算法题(18):常数时间删除节点 & 找到仅出现一次的两个数字
出题:给定链表的头指针和一个节点指针,要求在O(1)的时间复杂度下删除该节点 分析: 如果需要删除的节点为A,其前序节点为A-,其后续节点为A+,所以删除A之后,需要使得A-的下一个节点就是A+,常规 ...
- 两个有序数组长度分别为m,n,最多m+n次查找找出相同的数
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 一个整型数组里除了一个数字之外,其他的数字都出现了两次。要求时间复杂度是O(n),空间复杂度是O(1),如何找出数组中只出现一次的数字
思路分析:任何一个数字异或它自己都等于0,根据这一特性,如果从头到尾依次异或数组中的每一个数字,因为那些出现两次的数字全部在异或中抵消掉了,所以最终的结果刚好是那些只出现一次的数字. 代码如下: #i ...
- fcc的中级算法题
核心提示:这是网上开源编程学习项目FCC的javascript中级编程题(Intermediate Algorithm Scripting(50 hours)),一共20题.建议时间是50个小时,对于 ...
- leetcode算法题整理
一.线性表,如数组,单链表,双向链表 线性表.数组 U1.有序数组去重,返回新数组长度 A = [1,1,2] -> [1,2] 返回2 分析:其实一般数组的问题都可以用两个指针解决,一个指 ...
- LeetCode算法题-Power of Four(Java实现-六种解法)
这是悦乐书的第205次更新,第216篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第72题(顺位题号是342).给定一个整数(带符号的32位),写一个函数来检查它是否为4 ...
- LeetCode算法题-Power Of Three(Java实现-七种解法)
这是悦乐书的第204次更新,第215篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第71题(顺位题号是326).给定一个整数,写一个函数来确定它是否为3的幂.例如: 输入 ...
- FCC上的javascript算法题之中级篇
FCC中的javascript中级算法题解答 中级算法的题目中用到了很多js的知识点,比如迭代,闭包,以及对json数据的使用等等,现在将自己中级算法的解答思路整理出来供大家参考讨论.欢迎大家提出新的 ...
- [PHP] 算法-找出两个链表的第一个公共结点的PHP实现
输入两个链表,找出它们的第一个公共结点 1.两个单链表,有公共结点,那么必然,尾部公用 2.找出链表1的长度,找出链表2的长度,长的链表减去短的链表得出一个n值 3.长的链表先走n步,两个链表再同时移 ...
随机推荐
- HDU-------(2795)Billboard(线段树区间更新)
Billboard Time Limit: 20000/8000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 初学java之面板布局的控制
/* * 联系网格的布控laytout *以一个棋盘为列子吧! */ import javax.swing.*; import java.awt.*; class WindGrid extends J ...
- 张艾迪(创始人):发明整个世界+224C个国家
Eidyzhang:发明整个世界+224C个国家 Eidyzhang: Genius.Founder.CEO.23 I 世界级最高级创始人.世界最高级FounderCEO 出生在亚洲中国.Eidyzh ...
- 127. 126. Word Ladder *HARD* -- 单词每次变一个字母转换成另一个单词
127. Given two words (beginWord and endWord), and a dictionary's word list, find the length of short ...
- easyui $.parser.parse 页面重新渲染
一些dom元素是动态拼接上的easui的样式,由于页面已经渲染过了,所以需要手动执行渲染某个部件或者整个页面 $.parser.parse(); // parse all the page $.par ...
- struts2视频学习笔记 09-10(struts2处理流程,指定多个struts配置文件)
课时9 Struts2的处理流程 StrutsPrepareAndExecuteFilter是Struts 2框架的核心控制器,它负责拦截由<url-pattern>/*</url- ...
- BZOJ3888 [Usaco2015 Jan]Stampede
我们只要把每头牛开始遮挡视线和结束遮挡视线的时间点都搞出来就好= = 再按照y轴排序...然后变成线段覆盖了..线段树搞一下就好了? /******************************** ...
- Storm(4) - Distributed Remote Procedure Calls
Using DRPC to complete the required processing 1. Create a new branch of your source using the follo ...
- [原创]Keys的基本操作总结,判断Keys中是否存在Keys.Control|Keys.Alt,移除Keys中的部分键值。
直接看应用实例 /// <summary> /// 组合键转换成字符串类型 /// </summary> /// <param name="keyCode&qu ...
- UVALive 7297 Hounded by Indecision BFS
题目链接:Hounded by Indecision 题意:map中给出小偷的位置,警察的位置.警察有一只狗,开始的时候警察和狗一起行动,也就是看做一个格子,当警察遇见小偷走过的格子时,狗就会嗅到它的 ...