1 給出2n+1個數,其中有n個數是成對出現的,讓我找出裏面只出現了一次的那個數。
2 。給出2n+2個數,其中有n個數是成對出現的,讓我找出裏面只出現了一次的那兩個數。
對於第一個問題我們用位運算來解決中的異或運算,注意異或運算的運算法則:相同爲0,不同爲本身
代碼如下:
package yihuo;
public class yihuo {
public static void main(String[] args) {
// TODO Auto-generated method stub
int personal=0;
int personal1=0;
int a[]= {1,2,8,9,7,4,3,2,4,7,3,8,9,1,12};
for(int i=0;i<a.length;i++) {
personal=a[i]^personal;
}
System.out.println("出現了奇數次的那一個數 personal="+personal);
}
}
運行截圖:
2 。給出2n+2個數,其中有n個數是成對出現的,讓我找出裏面只出現了一次的那兩個數。
解題思路:因爲是偶數個不同(以),所以異或運算之後得到的是兩個不同元素的異或運算值,得不到想要的。但是如果我們把這一組數據分爲兩組,每一組分擔一個不同的,分組異或運算之後,每一組就會把那個單一元素給找出來。
i.困難:在不知道的情況下,如何將N+2個數據劃分爲我們想要的兩組。
ii.解決方法:將N+2個數據異或之後,將會得到我們想要的那兩個值的異或值,得到的這個異或值,它的二進制中肯定有至少一位是1(因爲不同),這裏我們取最高位是1的那一位,將所有數據中對應位按照該位置上是0和1分開,分成兩組,然後分組異或,將會得到兩個值,就是我們想要的結果了。
如何得到異或值的二進制最高一位爲1的位置呢,我用向左移動來實現。肯定有一個1,所以最壞情況是移動到最後成10000000,跳出循環。
for(;p<127;) {//一直向左移動,找到personal1剛開始爲1的位置也就是兩個數不同的位置。 p=p<<1; youyicount++; }
每次記錄向左移動次數,然後 location=8-youyicount;來得到那個位置。
爲了在location位置上將所有數據分成兩組,我想到0&n(任何數)都爲0,1&n(n是1則1,n是0則0),所以將每個值和2的location-1次方做與運算,如果結果爲零,說明該數據的二進制在location位置上爲0,否則爲1。根據0還是1得到兩組
代碼如下:
for(int i=0,j=0,m=0;i<b.length;i++) {
int t=b[i]&loc;
if(t==0) {
List1.add(b[i]);//兩個唯一的數,在第Location位置上不同,所以按照Location位置
// 上0或1分爲兩組,可以將兩個唯一值分開,分開後,按照上面的方法分別求即可
}else {
List2.add(b[i]);
}
}
得到兩組後,就回到第一個問題了,想了好久,覺得可以,點贊支持一下哦
完整代碼如下:
package yihuo;
import java.util.ArrayList;
public class yihuo {
// 給你n個數,其中有且僅有一個數出現了奇數次,其餘的數都出現了偶數次。
// 用線性時間常數空間找出出現了奇數次的那一個數。
public static void main(String[] args) {
// TODO Auto-generated method stub
int personal1=0;
int location=0;
int loc;
int one=0;
int two=0;
int youyicount=0;
int b[]= {1,2,8,9,7,4,2,4,7,3,8,1,12,10,12,10,28,20,28,20};
ArrayList List1 = new ArrayList();
ArrayList List2 = new ArrayList();
for(int i=0;i<b.length;i++) {
personal1=b[i]^personal1;
}
System.out.println("將N+2N個數異或計算得到personal1="+personal1);
int p=personal1;
for(;p<127;) {//一直向左移動,找到personal1剛開始爲1的位置也就是兩個數不同的位置。
p=p<<1;
youyicount++;
}
location=8-youyicount;//位置
System.out.println("兩個唯一值二進制不同的位置爲 location="+location);
loc=(int) Math.pow(2,location-1);//根據得到的位置,獲取需要的值
System.out.println("根據location得到關鍵值 loc="+loc);
for(int i=0,j=0,m=0;i<b.length;i++) {
int t=b[i]&loc;
if(t==0) {
List1.add(b[i]);//兩個唯一的數,在第Location位置上不同,所以按照Location位置
// 上0或1分爲兩組,可以將兩個唯一值分開,分開後,按照上面的方法分別求即可
}else {
List2.add(b[i]);
}
}
for(int i=0;i<List1.size();i++) {
int num=(int) List1.get(i);
one=(int)List1.get(i)^one;
}
for(int i=0;i<List2.size();i++) {
two=(int)List2.get(i)^two;
}
System.out.println("出現了奇數次的那一個數 one="+one);
System.out.println("出現了奇數次的那一個數 two="+two);
}
}
結果如圖: