劍指 offer之數組中只出現一次的數字_java

題目:數組中只出現一次的數字
題目描述
一個整型數組裏除了兩個數字之外,其他的數字都出現了兩次。請寫程序找出這兩個只出現一次的數字。

解題思路:
(1) 用map
(2)用異或

第一種思路的代碼實現:

//num1,num2分別爲長度爲1的數組。傳出參數
//將num1[0],num2[0]設置爲返回結果
import java.util.*;
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        //其餘都出現兩次
		if(array.length==2) {
			num1[0]=array[0];
			num2[0]=array[1];
			return;
		}
		//定義一個Map,
		Map<Integer,Integer> mp=new HashMap<>();
		for(int a:array) {
			if(mp.containsKey(a)) {
				mp.put(a, mp.get(a)+1);
			}else {
				mp.put(a, 1);
			}
		}
		Set<Integer> keySet = mp.keySet();
		Iterator<Integer> it = keySet.iterator();
		int [] temp=new int[2];
		int index=0;
		while(it.hasNext()) {
			int key=it.next();
			int val=mp.get(key);
			if(val==1) {
				temp[index++]=key;
			}
		}
		num1[0]=temp[0];
		num2[0]=temp[1];
    }
}

第二種思路:異或
解題思路:來自劍指 offer評論區
ps:又學會了一個招式,感覺好開心 :)
考慮過程:
首先我們考慮這個問題的一個簡單版本:一個數組裏除了一個數字之外,其他的數字都出現了兩次。請寫程序找出這個只出現一次的數字。
這個題目的突破口在哪裏?題目爲什麼要強調有一個數字出現一次,其他的出現兩次?我們想到了異或運算的性質:任何一個數字異或它自己都等於0 。也就是說,如果我們從頭到尾依次異或數組中的每一個數字,那麼最終的結果剛好是那個只出現一次的數字,因爲那些出現兩次的數字全部在異或中抵消掉了。
有了上面簡單問題的解決方案之後,我們回到原始的問題。如果能夠把原數組分爲兩個子數組。在每個子數組中,包含一個只出現一次的數字,而其它數字都出現兩次。如果能夠這樣拆分原數組,按照前面的辦法就是分別求出這兩個只出現一次的數字了。
我們還是從頭到尾依次異或數組中的每一個數字,那麼最終得到的結果就是兩個只出現一次的數字的異或結果。因爲其它數字都出現了兩次,在異或中全部抵消掉了。由於這兩個數字肯定不一樣,那麼這個異或結果肯定不爲0 ,也就是說在這個結果數字的二進制表示中至少就有一位爲1 。我們在結果數字中找到第一個爲1 的位的位置,記爲第N 位。現在我們以第N 位是不是1 爲標準把原數組中的數字分成兩個子數組,第一個子數組中每個數字的第N 位都爲1 ,而第二個子數組的每個數字的第N 位都爲0 。
現在我們已經把原數組分成了兩個子數組,每個子數組都包含一個只出現一次的數字,而其它數字都出現了兩次。因此到此爲止,所有的問題我們都已經解決。

代碼實現:

//num1,num2分別爲長度爲1的數組。傳出參數
//將num1[0],num2[0]設置爲返回結果
public class Solution {
    public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
        //首先找到異或後的結果
		//代碼的魯棒性
		if(array.length<2) {
			return;
		}
		if(array.length==2) {
			num1[0]=array[0];
			num2[0]=array[1];
			return;
		}
		//找到所有值的異或結果
		int temp=0;
		for(int a:array) {
			temp^=a;
		}
		//找到第一個二進制位中爲1的那個位置
		int index=getFirst1Bits(temp);
		for(int a:array) {
			if(isOne(a,index)) {
				num1[0]^=a;
			}else {
				num2[0]^=a;
			}
		}
	}
	private boolean isOne(int a, int index) {
		a=a>>index;
		return (a&1)==1;
	}
	private int getFirst1Bits(int temp) {
		int index=0;
		while((temp&1)==0 && index<32) {
			temp=temp>>1;
		    index++;
		}
		return index;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章