【力扣】136. 只出現一次的數字

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

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

示例:
示例 1:

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

示例 2:

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

一、哈希表 O(N) S(N)

這個思路很簡單:

  • 先利用哈希表存儲數字和數字出現次數,<key,value>,key保存數值,value保存該數字出現次數;每次hash[nums[i]]++表示出現次數。
  • 遍歷哈希表,可以選擇迭代器遍歷,或者使用auto變量即可以保存任何變量類型的變量來保存hash<key,value>,判斷value的值是否等於1,i.first得到key,i.second得到value,如果value==1,那麼返回key即爲答案。
int singleNumber(vector<int>& nums) 
{
	unordered_map<int,int>hash;
	for(int i=0;i<nums.size();i++)
	{
		hash[nums[i]]++;
	}
	for(auto i:hash)//遍歷哈希表
	{
		if(i.second==1)//判斷出現次數
		{
			return i.first;
		}
	}
	return 0;
}

但是這個解法使用了額外的空間,所以雖然可以通過但不是最優的。

二、排序 O(NlogN)

不使用額外空間的前提下,我們可以對數組進行排序:

  • 利用C++自帶函數對數組排序,那麼相同的數字就會在集中在一起。
  • 兩兩判斷是否相等,相等表示出現了2次,否則返回nums[i]即可,表示它是出現一次的。
  • 注意,防止最後一個數字爲出現一次的,要進行對i的判斷,判斷它是否爲最後一個數字,是表示出現了一次則返回即可。
int singleNumber(vector<int>& nums) 
{
	sort(nums.begin(),nums.end());
	for(int i=0;i<nums.size();i+=2)
	{
		if( i==nums.size()-1||nums[i]!=nums[i+1] )//最後一個數字防止越界
		{
			return nums[i];
		}
	}
	return 0;
}

排序最快的時間複雜度爲O(logN),雖然可以通過並不是線性時間複雜度。

三、最佳算法:位運算 O(N) S(1)

一定要記住,如果題目對時間,空間做出要求,利用一般解法無法做出,那麼要想到位運算,特別是異或。我們先看一下異或的性質:

  • 交換律:p⊕q=q⊕p
  • 結合律:p⊕(q⊕r)=(p⊕q)⊕r
  • 恆等率:p⊕0=p
  • 歸零率:p⊕p=0

那這個題目,只有一個數字出現了1次,其他都是2次,我們可以利用結合律,將出現偶數次數的數字異或,那麼結果爲0,如1⊕1=0;再和出現一次的⊕,那麼0⊕2=2,我們便可以找到這個重複的數字。記住,我們不用自己去調用結合律,系統自己會處理,如:數字【2,1,2】找出現一次的:
在這裏插入圖片描述
代碼如下:

//位運算異或交換律:1^1=0,1^0=1,1^2^1=1^1^2=2這樣就可以找到只出現一個的那個
int singleNumber(vector<int>& nums) 
{
	int sum=nums[0];;
	for(int i=1;i<nums.size();i++)
	{
		sum=nums[i]^sum;
	}
	return sum;
}

這個就是最佳解法,要牢記⊕的特性。

加油哦!💪。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章