136. Single Number
原题
Given an array of integers, every element appears twice except for
one. Find that single one.
Note:
Your algorithm should have liner runtime complexity. Could you
implement it without using extra memory?
题意
给定整数数组,除一个元素仅出现一次外,其他每个元素都出现两次。找出只出
现一次的元素。
注意:
算法具有线性运行复杂度。能否不使用额外的空间完成?
思路
- 要具有线性时间,可以利用
hashmap
的方式实现,首先遍历数组记录每个元
素出现的次数。然后遍历hashmap
找出出现次数为1
的元素。 - 题目指出不使用额外空间解决此问题,因此,上述解决方案不是最理想的。
注意到题目中明确指出数组中仅有一个元素出现一次,其他元素均出现两次,
而不是三次。由于一个数异或自身为零,因此,可以通过异或操作解决此问
题。只要是其他元素出现的次数是偶数次,都可以通过这种方法解决。 - 该问题也可以通过先对数组排序,然后遍历数组找出仅出现一次的元素。但
是基于比较的排序算法时间复杂度最低也为O(nlgn),无法满足线性时间。
计数排序、桶排序以及基数排序则可以提供线性时间的排序,不过对数据的
依赖比较强。
代码
思路1示例代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
map<int, int> numsCount;
for (int i = 0; i < nums.size(); ++i) {
numsCount[nums[i]]++; // The second element setted zero by default
}
for (map<int, int>::iterator it = numsCount.begin();
it != numsCount.end();
++it) {
if (it->second == 1) {
return it->first;
}
}
return 0;
}
};
思路2示例代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
int single = 0;
for (int i = 0; i < nums.size(); ++i) {
single ^= nums[i];
}
return single;
}
};
137. 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 liner runtime complexity. Could you
implement it without using extra memory?
题意
给定整数数组,除一个元素仅出现一次外,其他每个元素都出现三次。找出只出
现一次的元素。
注意:
算法具有线性运行复杂度。能否不使用额外的空间完成?
思路
- 同Single Number。利用
hashmap
的方式实现,首先遍历数组记录每个
元素出现的次数。然后遍历hashmap
找出出现次数为1
的元素。 - 上述方法需要使用额外空间,题目给出的疑问指示该问题同样可以在不是用
额外空间的前提下解决。注意到每个整数位在数组中出现的此数,例如有数
组[1,3,4,3,5,4,3,5,4,5]
,其二进制为
[0001, 0011, 0100, 0011, 0101, 0100, 0011, 0101, 0100, 0101]
,统
计数组中每bit
位出现1
的个数为0, 3, 3, 7
,取每位统计的个数模3
,
及得1
的二进制位0,0,0,1
。该方法可以推广到出现n
次的情况。
代码
思路1示例代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
map<int, int> numsCount;
for (int i = 0; i < nums.size(); ++i) {
numsCount[nums[i]]++;
}
map<int, int>::const_iterator it;
for (it = numsCount.begin(); it != numsCount.end(); ++it) {
if (it->second == 1) {
return it->first;
}
}
return 0;
}
};
思路2示例代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
int bits = sizeof(int) * 8;
int single = 0;
for (int i = 0; i < bits; ++i) {
int sum = 0;
for (int j = 0; j < nums.size(); j++) {
sum += (nums[j] >> i) & 0x01;
}
if (sum % 3) {
single |= (1 << i);
}
}
return single;
}
};
260. Single Number III
原题
Given an array of numbers nums
, in which exactly two elements appear
only once and all other elements appear exactly twice. Find the two
elements that appear only once.
For example:
Given nums = [1, 2, 1, 3, 2, 5]
, return [3, 5]
.
Note:
- The order of the result is not important. So in the above example,
[5, 3]
is also correct. - Your algorithm should run in liner runtime complexity. Could you
implement it using only constant space complexity?
题意
给定一个整数数组nums
,其中有两个元素仅出现一次,其他所有元素均出现两
次。找出仅出现一次的两个元素。
例如:
给定数组nums = [1, 2, 1, 3, 2, 5]
,返回[3, 5]
。
注意:
- 返回元素的顺序不重要。例如上面的例子中返回
[5, 3]
也是正确的。 - 线性时间复杂度。能否只用常量空间解决该问题?
思路
- 利用
hashmap
,类似于Single Number与Single Number II。 - 由于除了仅出现一次的元素外,其他元素均出现两次,那么通过异或就可以
得到这两个元素的异或值。此后在遍历数组,根据异或值的某一位将数组区
分为两个部分进行异或,求出仅出现一次的两个元素值。
代码
思路1示例代码
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
vector<int> singleNums;
map<int, int> numsCount;
for (int i = 0; i < nums.size(); ++i) {
numsCount[nums[i]]++;
}
map<int, int>::const_iterator it;
for (it = numsCount.begin(); it != numsCount.end(); ++it) {
if (it->second == 1) {
singleNums.push_back(it->first);
}
}
return singleNums;
}
};
思路2示例代码
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int xorVal = 0;
for (int i = 0; i < nums.size(); ++i) {
xorVal ^= nums[i];
}
xorVal &= -xorVal;
int single1 = 0, single2 = 0;
for (int i = 0; i < nums.size(); ++i) {
if (nums[i] & xorVal) {
single1 ^= nums[i];
} else {
single2 ^= nums[i];
}
}
vector<int> singleNums;
singleNums.push_back(single1);
singleNums.push_back(single2);
return singleNums;
}
};