1. 程式人生 > >劍指offer之陣列中只出現一次的數字

劍指offer之陣列中只出現一次的數字

1.題目描述

一個整型數組裡除了兩個數字之外,其他的數字都出現了偶數次。請寫程式找出這兩個只出現一次的數字。

2.問題分析

方法一:

可以使用map,統計每個數出現的次數,之後對兩個出現一次的數進行賦值

方法二:

這裡就數字的特性,首先我們需要知道:兩個相同的數異或後值為0。
可以用位運算實現,如果將所有所有數字相異或,則最後的結果肯定是那兩個只出現一次的數字異或的結果,所以根據異或的結果1所在的最低位,把數字分成兩半,每一半里都還有隻出現一次的資料和成對出現的資料這樣繼續對每一半相異或則可以分別求出兩個只出現一次的數字。具體例子見程式碼:

3.原始碼

方法一:

void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) 
{
    if(data.size() < 2)
        return;
    //統計次數
    map<int,int> times;
    for(int num:data)
        ++times[num];

    bool first =true;
    for(int num:data)
    {
    	//對查詢到次數為1的數進行賦值
        if(
times[num] == 1) { if(first == true) { first = false; *num1 = num; } else { *num2 = num; break; } } } }

方法二:

void FindNumsAppearOnce(vector<
int> data,int* num1,int *num2) { if(data.size() < 2) return; //使用異或,最後value的值是兩個出現一次的值的異或值,如3,4則異或結果是7 int value = 0; for(int num:data) value ^= num; //如果value = 0,則所有數都是偶次,沒有滿足題目要求,退出 if(value == 0) return; //如3(011),4(100),7(111) ,3和4兩個數的聯絡在於: // 二進位制中第一位就不同,3的第一位是1,4的第一位是0,所有兩個數的二進位制從低位到高位,第0位就不同了 //那麼可以根據這個特性,把陣列分成兩部分,一部分是 int index = 0; while((value & 1) == 0) { ++index; value >>= 1; } *num1 = 0; *num2 = 0; for(int num:data) { if(((num >> index) & 1) == 0) (*num1) ^= num; else (*num2) ^= num; } }