問題描述
Leetcode 137 Single Number II 僅出現一次的數字 中提出了一個更一般的問題:有一個數組,其中有一個元素出現了x次,其餘所有元素都出現了y次(x < y),找出這個出現了x次的元素,要求時間複雜度O(n),空間複雜度O(1)。
解題思路
實際上,Leetcode 136 Single Number 僅出現一次的數字 和 Leetcode 137 Single Number II 僅出現一次的數字 都是這個一般問題的特例。136是最特殊的一個例子,我們從中可以找到的規律不是很明顯;在137中我們已經給出使用one two three作爲掩碼來統計每一位上1的出現次數的方法,對於我們解決此題很有啓發。出現x次的情況下,我們用一個大小爲x的動態數組來存儲各掩碼即可,然後在每次獲取到一個數字後,循環更新所有的掩碼,最終第y個掩碼所代表的數字就是隻出現了y次的元素。
爲了統一處理,我們掩碼數組大小設爲x+1,用times[x+1]來表示,其中times[i]表示出現i次的位。
具體邏輯請看後面的代碼。
代碼
/**
* 返回特殊的數字
* 特殊數字僅出現y次,其餘數字均出現x次,x>0,y>0,x>y
* @param nums 數字集合
* @param numsSize 集合大小
* @param x 普通數字出現次數
* @param y 特殊數字出現次數
*/
int specialNumber(int *nums, int numsSize, int x, int y) {
int num, change, i;
int* times = (int*)malloc(sizeof(int) * (x + 1));
for (i = 1; i <= x; ++i) *(times + i) = 0;
while (numsSize) {
*times = ~0; // 置全1,保證*(times+1)結果的正確性
// 獲取當前要統計的數字
num = *(nums + --numsSize);
for (i = x; i > 0; --i) { // 更新每一位掩碼
change = *(times + i - 1) & num; // 獲得更新位
*(times + i) |= change; // 更新
num &= ~change; // 清空更新位
*(times + i - 1) &= ~change;
}
}
num = *(times + y);
free(times);
return num;
}
有了這個方法以後,我們在 Leetcode 136 Single Number 僅出現一次的數字 中的方法就可以如下實現:
/**
* 返回僅出現一次的數字
* 特殊數字僅出現1次,其餘數字均出現2次
* @param nums 數字集合
* @param numsSize 集合大小
*/
int singleNumber(int* nums, int numsSize) {
int specialNumber(int*, int, int, int);
return specialNumber(nums, numsSize, 2, 1);
}
同樣, 在Leetcode 137 Single Number II 僅出現一次的數字 中的方法就可以如下實現:
/**
* 返回僅出現一次的數字
* 特殊數字僅出現1次,其餘數字均出現3次
* @param nums 數字集合
* @param numsSize 集合大小
*/
int singleNumber(int* nums, int numsSize) {
int specialNumber(int*, int, int, int);
return specialNumber(nums, numsSize, 3, 1);
}
在leetcode上進行了驗證,136和137均Accept。
完整代碼 https://github.com/Orange1991/leetcode/blob/master/137/c/more.c
測試數據
[1,2,3,4,1,2,3,1,2,3] : each number appears 3 times expect for the special one appears 1 times, the special number is 4
[1,1,2,2,3,4,4,5,5,66,66] : each number appears 2 times expect for the special one appears 1 times, the special number is 3
[1,1,1,3,3,3,44,44,55,55,55,111,111,111] : each number appears 3 times expect for the special one appears 2 times, the special number is 44
[1] : each number appears 3 times expect for the special one appears 1 times, the special number is 1
2015/8/18