一道逻辑题 - 拿走了哪个数
来源:互联网 发布:淘宝男士手表货到付款 编辑:程序博客网 时间:2024/04/29 04:35
From: http://www.cnblogs.com/baiyanhuang/archive/2010/06/23/1763981.html
有1到10000共10000个数,如果我从中随机拿走一个数,你如何知道我拿走了哪个?
- 先把10000个数相乘,然后再将拿走一个数之后的9999个数相乘,两者相除即可。
这个算法是正确的,但是会有两个潜在的问题:- 如此多的数相乘,其范围必然会超出系统提供的数据类型支持,当然你可以实现自己的大数表示的算法,但那样性能必然有影响。
- 假设扩展一下题目,提供的数组中有0的话,乘法就不可用了。
- 针对前面提出的问题,同事想到了使用加法,先求出10000个数的和,再减去9999个数的和。
这样数据不会溢出,而且加法的效率比乘法也要高很多,即使数据中包含0,也没有任何问题。
然后就过关了,自己回去之后思考了一下,觉得还可以扩展,假设所有的数加起来之后仍然会溢出,那该如何处理,比如从1到(2^64-1),于是想到了位操作,与、或,异或中,要数异或最为神奇,代入一看,果然合适: 先将所有的数异或起来,然后将拿走一个数之后的数异或起来,两者结果再异或,便是拿走的那个数。
我用a,b,c,d4个数来做演示,因为异或符合结合律和交换律(你可以用0,1试一下),于是:
a^b^c^d = (a^b^c)^d
d = (a^b^c^d)^(a^b^c)
d = (a^b^c^d)^(a^b^c)
此处用异或的好处在于
- 不会溢出
- 异或的速度要快于加法
扩展一下题目,如果提供的不是整数,而是浮点数,会有问题吗?当然没有,因为是在位级别上操作,无论是整数还是浮点数,在这个算法看来,都是一堆位,处理起来没有什么差别。
再扩展一下题目,如果提供的数本身就超出了内置类型的表示范围,如在1到2^128,该如何处理?这个问题是在写这篇文章的过程中想到的,暂时没有好的办法。
- 一道逻辑题 - 拿走了哪个数
- 一道逻辑题 - 我拿走了哪个数
- 一道逻辑题 - 我拿走了哪个数
- 一道逻辑题 - 我拿走了哪个数
- 【算法】我拿走了哪个数?
- 一道逻辑题
- 一道逻辑题
- 一道逻辑题
- 一道编程题实在是不知道哪个地方错了
- 可可肉的逻辑题---(十)多了哪个呢?
- 一道C考试逻辑题
- 一道有趣的逻辑题
- 一道简单逻辑判断题
- 一道有意思的逻辑题
- 一道有趣的逻辑题
- 《游戏王》中的一道逻辑题
- 一道六嫌疑犯的逻辑判断题
- 一道六嫌疑犯的逻辑判断题
- css expression
- 甲骨文推出移动应用设计模式
- C#文件路径获取函数和文件名字获取函数
- gpio有关函数
- 浅析Android 4.2版本九大看点
- 一道逻辑题 - 拿走了哪个数
- 也说说extern "C"
- java 备份、还原oracle数据库
- 谷歌正式发布Android 4.2及Nexus新品
- 架设流媒体服务器
- 无须手动拼接 Android 4.2推新拍摄技术
- 新一代GoogleNexus手机采用硅谷数模SlimPort接口技术
- IBM将花2.5亿收购第二家以色列移动软件开发商
- 等待、验证我们结局的那一天