【本文链接】
http://www.cnblogs.com/hellogiser/p/find-k-missing-numbers-from-1-to-n.html
【题目】
从1到n,共有n个数字(无序排列),每个数字只出现一次。现在随机拿走一个数字x,请给出最快的方法,找到这个数字。要求时间复杂度为O(n),空间复杂度为O(1)。如果随机拿走k(k>=2)个数字呢?
【分析】
题目给出的条件很强,数字是从1~n的数字,限制了数字的范围;每个数字只出现一次,限制了数字出现的次数;随即拿走了一个数字,说明只有一处是与其他不同、不符合规律的。我们可以利用这些特点来选择合适的解法。
(1)Hash法。利用Hash法统计数字出现的次数,次数为0的即为所求。时间复杂度O(n),空间复杂度O(n)。通常这不是面试、笔试时想要的答案,但是Hash的优势在于其通用性。
(2)排序法。利用快排,得到排序后的数组,然后顺序遍历,统计次数为0的数字。时间复杂度O(nlgn),空间复杂度O(1)。其时间复杂度略高,通常也不是面试官期待的解法,但排序法也算是一种通用做法。
(3)元素相乘/相加法。时间复杂度O(n),空间复杂度O(1)。
元素相乘法:由于只有一个元素被拿走,因此我们只需要先算出n的阶乘n!,再除以现存所有数字的乘积M,即可得到拿走的数字x
(x=n!/M)。但是且缺陷是n不能太大,否则会溢出。
元素相加法:先算出从1到n的所有数字的和Sn,然后减去现有所有数字的和sum,即可得到拿走的数字x(x=Sn-sum)。元素相加法比元素相乘要更好一些。
(4)位运算。时间复杂度O(n),空间复杂度O(1)。
位运算法如果可以使用的话,应该是计算最快的方法。但是位运算对条件要求也较苛刻,一般需要元素有特殊规律,才有可能使用这种方法。在本题目中,对1~n所有元素进行xor运算得到A=1^2^3^…^(x-1)^x^(x+1)^…^n,在对取走一个元素后剩下的元素进行xor运算得到B=1^2^3^…^(x-1)^(x+1)^…^n,二者xor即可得拿走的数字x
= A^B。因为在A^B的过程中相同的数字都被抵消掉了,剩余的结果即为x。
【代码】
C++
Code
1 |
// 61_FindMissingNumberFrom1toN.cpp : Defines the entry point for the console application. |
【扩展】
如果随机拿走两个数字呢?如果随机拿走k(k>2)个数字呢?
(1)(2)是通用做法,仍适合。
(3)扩展:
K=1时,构造2个等式。
Sa = 1+2+…(x-1)+x+(x+1)…+n
Sb = 1+2+…(x-1)+(x+1)…+n
X = Sa-Sb
K=2时,构造4个等式。
S2a = 12+22+…+x2+…+y2+…+n
S2b =
12+22+…(x-1)2+(x+1)2…+(y-1)2+(y+1)2…+n
S1a = 1+2+…+x+…+y+…+n
S1b = 1+2+…(x-1)+(x+1)…+(y-1)+(y+1)…+n
则有x2+y2=S2a-S2b,x+y =S1a-S1b。可以求解得到x和y。
同理(k>2),构造2*k个等式,可以得到关于k个数的k个方程,求解即可得到k个数字。
(4)扩展:
思考一下,如何扩展?
【参考】
http://ouscn.diandian.com/post/2013-10-06/40052170552
【本文链接】
http://www.cnblogs.com/hellogiser/p/find-k-missing-numbers-from-1-to-n.html
61.
从1到n,共有n个数字,每个数字只出现一次。从中随机拿走一个数字x,请给出最快的方法,找到这个数字。如果随机拿走k(k>=2)个数字呢?[find k
missing numbers from 1 to n]