劍指offer 陣列中只出現一次的數字
題目描述:
一個整型陣列裡除了兩個數字之外,其他的數字都出現了兩次。請寫程式找出這兩個只出現一次的數字。
- 輸入:
-
每個測試案例包括兩行:第一行包含一個整數n,表示陣列大小。2<=n <= 10^6。第二行包含n個整數,表示陣列元素,元素均為int。
- 輸出:
-
對應每個測試案例,輸出陣列中只出現一次的兩個數。輸出的數字從小到大的順序。
- 樣例輸入:
- 8
2 4 3 6 3 2 5 5 - 樣例輸出:
- 4 6
- 先看一個簡單點的問題,如果只有一個數出現了一次,那麼狠明顯把所有的數異或起來就得到了這個只出現了一次的數。
- 那麼再來看這個問題,如果我們把所有的數異或起來,那麼我們得到的就是這兩個數異或起來的值,設這兩個數為x,y.
- a1^a2^a3^...^an=x^y = z != 1.
- 那麼我們設想能不能將其分成兩類。我們找到z的最低位的1然後對其進行分析,可以得出
- 1.這n個數中這一位為1的數一定有奇數個,
- 2.x,y中一定有一個數的這一位為1,另一個這一位為0.
- 3.那麼這n個數種這一位為0的肯定也有奇數這。
- 那麼我們就將其分成了兩類了。
- 將這一位為1的全部異或起來,將這一位為0的全部異或起來,分別可以得到一個數。
- 程式碼如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6+10;
int a[maxn];
int main()
{
int n;
while(~scanf("%d",&n)){
int ans= 0,num1=0,num2=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
ans^=a[i];
}
int x = ans&(-ans);
for(int i=0;i<n;i++){
if(x&a[i]) num1^=a[i];
else num2^=a[i];
}
printf("%d %d\n",min(num1,num2),max(num1,num2));
}
return 0;
}
我們繼續分析這個問題。如果有三個數出現的次數為1次,剩下的都是兩次呢?
我們接著上面的思路進行分析。這這三個數為x,y,z.
a[1]^a[2]^...^a[n] = ans = x^y^z != 0;
根據這個我們可以得出
ans^x != 0, ans^y !=0 , ans^z !=0;
然後我們根據上面的思路分析 取ans的最低位1,因為ans>0因此肯定存在一個最低位的1
那麼又因為 ans^x^ans^y^ans^z = ans 那麼就存在兩種情況,
1) ans^x, ans^y, ans^z的這一位全為1.
證明:如果滿足,ans^x,ans^y,ans^z的這一位都是1的情況下那麼x,y,z的這一位就都是0了,又因為ans=x^y^z,
如果這一位都是0的話那麼ans的這一位肯定是0,相互矛盾,故不可能。
2) 其中一個的這一位為1,剩下的兩個的這一位為0.
根據這一點我們可以將其分成兩類了。然後將這n個數這一位為1的進行異或可以求出一個值。
算出來之後將這個值加入到陣列中,就只有兩個數未知了,根據上面的解法就可以求出來了。
程式碼如下:
#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 1e6+10;
int a[maxn];
int main()
{
int n;
while(~scanf("%d",&n)){
int tot = 0,x=0,y=0,z=0;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
tot^=a[i];
}
int m=tot&(-tot);
for(int i=0;i<n;i++)
if(m&a[i]) x^=a[i];
tot^=x;
a[n]=x;
m = tot&(-tot);
for(int i=0;i<=n;i++){
if(m&a[i]) y^=a[i];
else z^=a[i];
}
printf("%d %d %d\n",x,y,z);
}
return 0;
}
/****
5
1 1 2 3 4
3
7 8 9
7
11 11 2 2 3 4 5
9
1 1 2 2 3 3 4 5 6
***/
相關文章
- 劍指 Offer 56 - I. 陣列中數字出現的次數陣列
- 劍指Offer--陣列中重複的數字陣列
- 找出陣列中只出現一次的數字陣列
- 劍指offer:旋轉陣列的最小數字陣列
- 劍指offer 旋轉陣列的最小數字陣列
- Leetcode 劍指 Offer 03. 陣列中重複的數字LeetCode陣列
- 劍指offer-轉陣列的最小數字-php陣列PHP
- JZ-040-陣列中只出現一次的數字陣列
- 劍指Offer-39-數字在排序陣列中出現的次數排序陣列
- 劍指OFFER-數字在升序陣列中出現的次數(Java)陣列Java
- 【劍指offer】7.旋轉陣列的最小數字陣列
- 【劍指 Offer】11. 旋轉陣列的最小數字陣列
- 劍指 Offer 11. 旋轉陣列的最小數字陣列
- 劍指offer刷題之路--1.陣列中重複的數字陣列
- [劍之offer] 03 陣列中重複的數字陣列
- 劍指offer之列印超過陣列一半的數字陣列
- 劍指 offer(1) -- 陣列篇陣列
- [劍指offer題解][Java]陣列中出現次數超過一半的數字Java陣列
- Leetcode 劍指 Offer 39. 陣列中出現次數超過一半的數字LeetCode陣列
- 劍指Offer-把陣列中的數排成一個最小的數陣列
- 【劍指offer】二維陣列中的查詢陣列
- (python版)《劍指Offer》JZ06:旋轉陣列的最小數字Python陣列
- 劍指Offer-37-陣列中逆序對陣列
- 劍指Offer-34-把陣列排成最小的數陣列
- 劍指offer——把陣列排成最小的數C++陣列C++
- 力扣 - 劍指 Offer 39. 陣列中出現次數超過一半的數字力扣陣列
- 【劍指offer】【1】二維陣列中的查詢陣列
- 劍指offer——陣列中的逆序對C++(75%)陣列C++
- (python版)《劍指Offer》JZ34:第一個只出現一次的字元Python字元
- 每日一題 - 劍指 Offer 53 - I. 在排序陣列中查詢數字 I每日一題排序陣列
- 二維陣列中的查詢——牛客劍指offer陣列
- 劍指 Offer 04. 二維陣列中的查詢陣列
- 劍指Offer-連續子陣列中的最大和陣列
- 劍指offer之順序列印陣列陣列
- 力扣 - 劍指 Offer 45. 把陣列排成最小的數力扣陣列
- 劍指 offer 第一題: 二維陣列中的查詢陣列
- 1. 二位陣列中的查詢(劍指offer)陣列
- LeetCode 只出現一次的數字LeetCode
- 136只出現一次的數字