算法-只出現一次的數字(原理講解)

這三道題目也是Leetcode上的,考察的是對位運算的掌握程度。當然用HashMap也是可以做的。這裏只講位運算。

1、只出現一次的數字(I)

136. 只出現一次的數字

給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現兩次。找出那個只出現了一次的元素。

說明:

你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?

示例 1:

輸入: [2,2,1]
輸出: 1
示例 2:

輸入: [4,1,2,1,2]
輸出: 4

我們知道兩個相同的數字異或後結果爲0,任何數字和0異或等於它本身,所以我們將數組所有元素異或就得到解。

    public int singleNumber(int[] nums) {
        int n=0;
        for(int i=0;i<nums.length;i++){
            n^=nums[i];
        }
        return n;
    }

2、只出現一次的數字(II)

137. 只出現一次的數字 II

給定一個非空整數數組,除了某個元素只出現一次以外,其餘每個元素均出現了三次。找出那個只出現了一次的元素。

說明:

你的算法應該具有線性時間複雜度。 你可以不使用額外空間來實現嗎?

示例 1:

輸入: [2,2,3,2]
輸出: 3
示例 2:

輸入: [0,1,0,1,0,1,99]
輸出: 99

我在這裏直接給出一個通用解法,在1個非空整數數組,除了某個元素出現1次以外,其他數字都出現k次。

我們對數組中每個數字的每一位進行檢查,如果統計對應位的1的數量不爲k的整數倍時,說明其是組成目標數字的位,反之不是,然後用按位或的操作就可以得到結果了
當k=3時,就是本題的答案,當k=2時,就是1的答案。

//nums:輸入數組  k:除某個元素外,剩餘元素都出現k次
public int singleNumber(int[] nums,int k) {
	int result=0;
	for(int i=0;i<32;i++){
		int mask=1<<i;
		int maskCount=0;
		for(int n:nums){
			if((n&mask)!=0){
				maskCount++;
			}
		}
		if(maskCount%k!=0){
			result|=mask;
		}
	}
	return result;
}

3、只出現1次的數字(III)

260. 只出現一次的數字 III

給定一個整數數組 nums,其中恰好有兩個元素只出現一次,其餘所有元素均出現兩次。 找出只出現一次的那兩個元素。

示例 :

輸入: [1,2,1,3,2,5]
輸出: [3,5]
注意:

結果輸出的順序並不重要,對於上面的例子, [5, 3] 也是正確答案。
你的算法應該具有線性時間複雜度。你能否僅使用常數空間複雜度來實現?

本題考察的仍然是位運算,延續1的思路,我們首先可以把所有數據異或,最後剩下的就是那兩個只出現一次的元素(記錄爲a、b)的異或值。

其中,這個值的非零位必然是屬於其中一個的,而不屬於另一個,這樣的話我們就將數據分成了兩部分,除a外的所有在此位和a相同的位元素組成的數組 同理b也是。

    public int[] singleNumber(int[] nums) {
		int result=0;
		for(int i:nums){
			result^=i;
		}
		int a=0,b=0;
		for(int i=31;i>=0;i--){//找到第一個非0位
			int mask=1<<i; 
			if((result&mask)!=0){//找到那一位
				for(int n:nums){//遍歷數組,將數組分爲兩類
					if((n&mask)!=0){
						a^=n;
					}else{
						b^=n;
					}
				}
				break;
			}
		}
		return new int[]{a,b};
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章