牛客網刷題32—數組中值出現了一次的數字


59.數組中值出現了一次的數字

題目鏈接

https://www.nowcoder.com/practice/200d8d789f9f431999fac795bb094356?tpId=101&&tqId=33215&rp=5&ru=/activity/oj&qru=/ta/programmer-code-interview-guide/question-ranking

題目描述

給定一個數字arr,其中只有有兩個數字出現了奇數次,其它數字都出現了偶數次,按照從小到大順序輸出這兩個數。

輸入描述:

輸入包含兩行,第一行一個整數n(1≤n≤105),代表數組arr的長度,第二行n個整數,代表數組arr,arr[i]為32位整數。

輸出描述:

輸出出現奇數次的兩個數,按照從小到大的順序。
示例1

輸入

4
1 1 2 3

輸出

2 3
示例2

輸入

6
11 22 11 23 23 45

輸出

22 45

備注:

時間復雜度O(n)O(n),額外空間復雜度O(1)O(1)。

關鍵技術

  1. 按位異或。
  2. 左移。

題目分析

  1. 用換行符分割出n,用空格分割出arr;
  2. 相同的數字取異或為0,不同的數字取異或為1,所以arr中所有數字的異或(sum)為兩個出現奇數次的數字(str_1,str_2)的異或,即sum = str_1 ^ str_2;
  3. 在sum中為1的位置上,str_1和str_2必不相等,一個為1,一個為0。(若sum為11001,那么在k=0,1,4時,str_1的第0位,第1位和第4位與str_2的第0位,第1位和第4位上的數字不相等;
  4. 若想取出第一個不相等的位置(在上邊例子中,k=0),即找出sum中第一個1出現的位置,此位置賦給k;
  5. 通過判斷k位置上是否為1,可以把數字分成兩組,一組是k位置上為1,另一組是k位置上不為1;
  6. 此時分別找兩組數中出現奇數次數的數,即第一組中有一個數出現了奇數次,第二組中有一個數出現了奇數次。
  7. 一組數中,有一個數出現奇數次,那么這組數異或以后的數就是出現奇數次的數。
  8. 分別求出兩組數的異或值后,排序輸出。
var input = [];
var res = [];
while(input = readline()){
    res += input + '\n';
}
//用換行符分割出n
var n = res.split('\n')[0];
//用空格分割出arr
var arr = res.split('\n')[1].split(' ');
var sum;
for(let i=0;i<n;i++){
    sum ^= arr[i];
}
var s_1, s_2;
var k = 0; 
//取出第一個為 1 的下標 
while(!(sum & 1)){
    sum = sum >> 1;
    k++;
}
//找出出現了奇數次的數
for(let i=0;i<n;i++){
    if((arr[i] >> k) & 1){
        s_1 ^= arr[i];
    }else{
        s_2 ^= arr[i];
    }      
}
//按從小到大順序輸出
print(s_1 < s_2 ? s_1:s_2,s_1 > s_2 ? s_1:s_2);

  

 
        


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM