国产精品一久久香蕉产线看-国产精品一区在线播放-国产精品自线在线播放-国产毛片久久国产-一级视频在线-一级视频在线观看免费

程序員面試題100題(63)-數組中三個只出現一次的數字[算法]

時間:2022-07-13 23:32:10 面試 我要投稿
  • 相關推薦

程序員面試題精選100題(63)-數組中三個只出現一次的數字[算法]

題目:一個數組中有三個數字a、b、c只出現一次,其他數字都出現了兩次。請找出三個只出現一次的數字。

程序員面試題精選100題(63)-數組中三個只出現一次的數字[算法]

分析:我們討論了如何在一個數組中找出兩個只出現一次的數字。在這道題中,如果我們能夠找出一個只出現一次的數字,剩下兩個只出現一次的數字就很容易找出來了。

如果我們把數組中所有數字都異或起來,那最終的結果(記為x)就是a、b、c三個數字的異或結果(x=a^b^c)。其他出現了兩次的數字在異或運算中相互抵消了。

我們可以證明異或的結果x不可能是a、b、c三個互不相同的數字中的任何一個。我們用反證法證明。假設x等于a、b、c中的某一個。比如x等于a,也就是a=a^b^c。因此b^c等于0,即b等于c。這與a、b、c是三個互不相同的三個數相矛盾。

由于x與a、b、c都各不相同,因此x^a、x^b、x^c都不等于0。

我們定義一個函數f(n),它的結果是保留數字n的二進制表示中的最后一位1,而把其他所有位都變成0。比如十進制6表示成二進制是0110,因此f(6)的結果為2(二進制為0010)。f(x^a)、f(x^b)、f(x^c)的結果均不等于0。

接著我們考慮f(x^a)^f(x^b)^f(x^c)的結果。由于對于非0的n,f(n)的結果的二進制表示中只有一個數位是1,因此f(x^a)^f(x^b)^f(x^c)的結果肯定不為0。這是因為對于任意三個非零的數i、j、k,f(i)^f(j)的結果要么為0,要么結果的二進制結果中有兩個1。不管是那種情況,f(i)^f(j)都不可能等于f(k),因為f(k)不等于0,并且結果的二進制中只有一位是1。

于是f(x^a)^f(x^b)^f(x^c)的結果的二進制中至少有一位是1。假設最后一位是1的位是第m位。那么x^a、x^b、x^c的結果中,有一個或者三個數字的第m位是1。

接下來我們證明x^a、x^b、x^c的三個結果第m位不可能都是1。還是用反證法證明。如果x^a、x^b、x^c的第m位都是1,那么a、b、c三個數字的第m位和x的第m位都相反,因此a、b、c三個數字的第m位相同。如果a、b、c三個數字的第m位都是0,x=a^b^c結果的第m位是0。由于x和a兩個數字的第m位都是0,x^a結果的第m位應該是0。同理可以證明x^b、x^c第m位都是0。這與我們的假設矛盾。如果a、b、c三個數字的第m位都是1,x=a^b^c結果的第m位是1。由于x和a兩個數字的第m位都是1,x^a結果的第m位應該是0。同理可以證明x^b、x^c第m位都是0。這還是與我們的假設矛盾。

因此x^a、x^b、x^c三個數字中,只有一個數字的第m位是1。于是我們找到了能夠區分a、b、c三個數字的標準。這三個數字中,只有一個數字滿足這個標準,而另外兩個數字不滿足。一旦這個滿足標準數字找出來之后,另外兩個數字也就可以找出來了。

這種思路的C++代碼如下:

void getThreeUnique(vector& numbers, vector& unique)

{

if(numbers.size() < 3)

return;

int xorResult = 0;

vector::iterator iter = numbers.begin();

for(; iter != numbers.end(); ++iter)

xorResult ^= *iter;

int flags = 0;

for(iter = numbers.begin(); iter != numbers.end(); ++iter)

flags ^= lastBitOf1(xorResult ^ *iter);

flags = lastBitOf1(flags);

// get the first unique number

int first = 0;

for(iter = numbers.begin(); iter != numbers.end(); ++iter)

{

if(lastBitOf1(*iter ^ xorResult) == flags)

first ^= *iter;

}

unique.push_back(first);

// move the first unique number to the end of array

for(iter = numbers.begin(); iter != numbers.end(); ++iter)

{

if(*iter == first)

{

swap(*iter, *(numbers.end() - 1));

break;

}

}

// get the second and third unique numbers

getTwoUnique(numbers.begin(), numbers.end() - 1, unique);

}

int lastBitOf1(int number)

{

return number & ~(number - 1);

}

void getTwoUnique(vector::iterator begin, vector::iterator end, vector& unique)

{

int xorResult = 0;

for(vector::iterator iter = begin; iter != end; ++iter)

xorResult ^= *iter;

int diff = lastBitOf1(xorResult);

int first = 0;

int second = 0;

for(vector::iterator iter = begin; iter != end; ++iter)

{

if(diff & *iter)

first ^= *iter;

else

second ^= *iter;

}

unique.push_back(first);

unique.push_back(second);

}

上文中getThreeUnique從數組中找出三個只出現一次的數字,而getTwoUnique從數組中找出兩個只出現一次的數字。lastBitOf1實現分析中的函數f(n)的功能,它只保留數字n的二進制表示中的最后一位1,而把其他所有位都變成0。

在函數getThreeUnique中,我們通過第一個for循環把a、b、c三個數字異或的結果保存到xorResult中,接著在第二個for循環中求出f(x^a)^f(x^b)^f(x^c)并保存到變量flags中。在語句flags=lastBitOf1(flags)求出f(x^a)^f(x^b)^f(x^c)結果的二進制中最后一位是1的位。并根據這一數位求出第一個只出現一次的數字first。接著把first交換到數組的最后,并在數組的前n-1個數字中求出另外兩個只出現一次的數字。


[程序員面試題精選100題(63)-數組中三個只出現一次的數字[算法]]相關文章:

1.程序員面試題精選100題(63)-數組中三個只出現一次的數字[算法]

2.微軟面試100題系列

【程序員面試題100題(63)-數組中三個只出現一次的數字[算法]】相關文章:

程序員面試題精選100題-字符串的組合[算法]07-13

程序員精選面試題100題07-13

程序員面試題-求Fibonacci數列[算法]07-13

另一道遞歸算法題(2009年企業面試題)07-13

JAVA算法面試題:哪位高人會做?07-13

淘寶面試題求解--數據挖掘-算法07-13

2014年MBA面試題目大綱100題07-11

程序員面試題精選07-12

今天參加了華為的面試,被一個算法題水了?07-11

主站蜘蛛池模板: 日韩在线操 | 日韩视频在线观看视频 | 搞黄网站在线观看 | 亚洲视频一区 | 亚洲 欧洲 日产 韩国在线 | 亚洲免费国产 | 中国国产一级毛片 | 男女羞羞免费视频 | 国产欧美一区二区成人影院 | 欧洲在线 | 久爱精品视频在线视频 | 丝袜免费网站 | 大桥未久aⅴ一区二区 | 二区三区在线观看 | 999精品久久久中文字幕蜜桃 | 日韩激情视频网站 | 精品欧美一区二区在线看片 | 九九伦理影院手机观看 | 我想看黄色毛片 | 婷婷视频在线观看 | 亚洲激情在线视频 | 欧美成人免费做真爱大片 | 中国美女挠脚心丝袜vk | 在线免费观看a级片 | 高清freexxxx性| 曰本女人色黄网站 | 黄色福利| 午夜视频网址 | 天天操天天操天天操香蕉 | 免费看黄视频网站 | 免费成人在线网站 | 午夜体验 | 好男人社区成人影院在线观看 | 成人免费动作大片黄在线 | 国产aaaaaaa毛片 | 日日噜噜夜夜狠狠va视频 | 人喾交性专区免费看 | 精品国产91乱码一区二区三区 | 亚洲另类精品xxxx人妖 | 国内性经典xxxxx | 日韩福利片 |