1. 程式人生 > >LeetCode Single Number I & II 都符合兩個問題額外要求的 通用解法 與 思考過程

LeetCode Single Number I & II 都符合兩個問題額外要求的 通用解法 與 思考過程

 Single Number

Given an array of integers, every element appearstwiceexcept for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

Single Number II

Given an array of integers, every element appearsthreetimes except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?

首先本能地想到一個演算法,可是腦子一轉,覺得是要O(n*n)時間複雜度。編譯一下,果然沒通過。程式如下:不過我覺得本演算法最簡單,而且通用性是最好的。

int singleNumber(int A[], int n) {
		for(int i = 0; i < n; i++)
		{
			if(count(A, A + n, A[i])<2)
				return i;
		}
	}

然後搜腸刮肚想想那個演算法可以優化為時間O(n)的複雜度的?分治?減治?貪心?動態規劃???想多了。

好吧,本能地分析吧:

1. 要求複雜度為O(n),白話點說也就是不能在一個n次迴圈裡面新增任何迴圈,前面之所以失敗就是因為這個原因。但是可以在迴圈外新增迴圈!!!

2. 既然可以在查詢迴圈外新增迴圈,那麼新增什麼迴圈好呢?排序吧,沒錯!排序的數列幹什麼都方便!(感覺這個結論也適用很多地方)

排序之後就可以很方便地計算一個數在數列中出現了多少次了。一連出現多少次就是總共出現多少次了,方便吧。O(∩_∩)O~

然後開始寫程式碼了,wait!我覺得動手之前還是先考慮一下特殊情況吧。特殊情況一般是邊界問題:

1. 如果數列外空呢?

2 如果第一個是single number呢?

3 如果最後一個是single number呢?

好了,分析完就可以寫程式碼了!下面程式碼適合兩個問題,只需要把出現次數修改為對應的2或3次數就可以了。而且不需要額外的空間!

//通用性好,適合兩種情況
	int singleNumber(int A[], int n) {
		//特殊情況1,2
		if(n<=0) return -1;
		if(n==1) return A[0];

		sort(A, A + n);
		int j = 1;
		for(int i = 0; i < n - 1; i++)
		{
			if(A[i] == A[i+1])
				j++;
			else 
			{
				if(j<2) return A[i];//這裡修改為j<3那麼就可以適用於single number II了。
 				j = 1;
			}
		}

		//特殊情況3 最後一個是single number的特殊情況
		return A[n-1];
	}


相對簡單。

2014-3-6更新:

好了,更新不說通用性了。上面的基本排序處理的確是很通用的,屬於基本演算法內容了,沒什麼值得深入探討的。 想不到這篇文章有幸可以有這麼多人閱讀。 這裡更新下解說。 本題型別有三種解法的: 1 如上面的排序後處理的方法 2 利用map處理,效率也接近O(n) 3 位運算操作解法-這裡也主要可以分兩種解法 下面程式是利用unordered_map解Single number I的程式(Single number II是一樣道理):
//2014-2-18 update
	int singleNumber(int A[], int n) 
	{
		unordered_map<int, bool> ump_ii;
		for (int i = 0; i < n; i++)
		{
			if (!ump_ii.count(A[i])) ump_ii[A[i]] = true;
			else ump_ii.erase(A[i]);
		}
		return ump_ii.begin()->first;
	}

下面是Single number I 的位運算解法,思路就是每位bit出現2次就清零,所以可以不斷異或運算得出最終結果:

//2014-2-18_2 update
	int singleNumber(int A[], int n) 
	{
		int ans = 0;
		for (int i = 0; i < n; i++) ans ^= A[i];
		return ans;
	}

Single number II 的位運算兩種解法-- 參考leetcode論壇的程式碼:

方法一,int的32個bit逐個處理-這個方法還算簡單的了:

int singleNumberII_36(int A[], int n)
{
	int ans = 0;
	for (int i = 0; i < 32; i++) 
	{
		int c = 0, d = 1<<i;
		for (int j = 0; j < n; j++)
			if (A[j] & d) c++;

		if (c%3) ans |= d;
	}
	return ans;
}

方法二,進位,掩碼清零法-本方法還是挺難理解的,要很小心,否則,很容易出錯的,對位運算不熟悉是很難寫出來的。

int singleNumber(int A[], int n)
{
	int one = 0, two = 0;
	for (int i = 0; i < n; i++)
	{
		two |= A[i] & one;//two 積累值
		one ^= A[i];//one不斷求反
		int t = one & two;//第三次的時候one和two都保留了該位的值
		one &= ~t;//清零出現三次的該位的值
		two &= ~t;
	}
	return one;
}

好了,網上也有其他Single number II的變異的位運算演算法,不過都不太好理解。Single NumberII可以說高達5星級難度了。

不過上面的位運算方法一還是算好理解的了,而且也比較容易就可以用在其他情況,比如所有numbers都出現5次其中一個除外,面試的時候我覺得應該是首推演算法吧。

相關推薦

LeetCode Single Number I & II 符合問題額外要求通用解法 思考過程

 Single Number Given an array of integers, every element appearstwiceexcept for one. Find that single one. Note: Your algorithm should ha

SINGLE NUMBER I & II & III

Single Number I : Given an array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm s

LeetCode(41) Single Number III

Single Number I 題目描述 Given an array of integers, every element appears twice except for one. Find that single one. 如果一個給定陣列中除了一個元素其他所有元素均出

LeetCode Single Number II

Problem Given an array of integers, every element appears three times except for one, which appears exactly once. Find tha

[LeetCode] Single Number II 單獨的數字之二

Given an array of integers, every element appears three times except for one. Find that single one. Note:Your algorithm should have a linear runtime com

LeetCode (39) Ugly Number I II (醜數)

Ugly Number I 題目描述 Write a program to check whether a given number is an ugly number. Ugly numbers are positive numbers whose prime factor

陣列中出現一次的個數 leetcode Single Number III

class Solution { public: vector<int> singleNumber(vector<int>& nums) { vector<int> res; if(nums.size()==0) return

[LeetCode] Single Number

could implement col algo public xtra arr com note Given an array of integers, every element appears twice except for one. Find that singl

LeetCode——Single Number

i++ entry 思路 etc 給定 size cep ret entryset Given an array of integers, every element appears twice except for one. Find that single

leetcode single-number

ole could subject ber 使用 代碼 [] ron lin 題目描述 Given an array of integers, every element appears twice except for one. Find that single

[LeetCode]single-number

integer near csdn mem tail ext 滿足 相同 返回 題目:Given an array of integers, every element appears twice except for one. Find that single one.

LeetCode - Two Sum I - II - III - IV、3Sum、3Sum Closest、4Sum、4Sum II 系列學習總結

目錄 1 - Two Sum 2 - Two Sum II - Input array is sorted 3 - Two Sum III - Data structure design 4 - Two Sum IV - Input is a BST 5 - 3Sum

leetcode Single Number

Single Number 題目:https://leetcode.com/problems/single-number/ 一個數組中只有一個數字出現一次,其餘的數字都出現兩次,要求時間複雜度是O(n),空間複雜度O(1) public static void main(String[] a

LeetCode——Single Number(136)

Given a non-empty array of integers, every element appears twice except for one. Find that single one. Note: Your algorithm should have

[LeetCode] Single Number 單獨的數字

Given an array of integers, every element appears twice except for one. Find that single one. Note:Your algorithm should have a linear runtime complexit

[LeetCode] Single Number III 單獨的數字之三

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements tha

[leetcode] Single Number III

同Single Number,異或後按照得到的結果中bit位為1的將陣列分為兩組,結果必然各存在於這兩組中,分別異或得到結果。程式碼如下: vector<int> singleNumber(vector<int>& nums) {

Leetcode: Unique Path I & II, Minimum Path Sum, Triangle

這四個題都是比較直觀的DP題,題目中已經暗示了我們怎麼Cache遞迴表示式算出來的資料,我們可以採取和題目中一樣的矩陣,或者節省一部分空間採用滾動陣列解題 Problem 1: Unique Path I A robot is located at the top-le

Leetcode刷題(python)之 陣列的交集 II

給定兩個陣列,寫一個方法來計算它們的交集。例如:給定nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].注意:  輸出結果中每個元素出現的次數,應與元素在兩個陣列中出現的次數一致。   我們可以不考慮輸出結果的順序。跟進:如果給定的

Leetcode】【簡單】【350. 陣列的交集 II】【JavaScript】

題目描述 350. 兩個陣列的交集 II 給定兩個陣列,編寫一個函式來計算它們的交集。 示例 1: 輸入: nums1 = [1,2,2,1], nums2 = [2,2]輸出: [2,2] 示例 2: 輸入: nums1 = [4,9,5], nums2 = [9,4,9,8,4]輸出: [4,9] 說明