136. 只出现一次的数字
描述
- 给定一个整数数组,除了某个元素外其余元素均出现两次。请找出这个只出现一次的元素。
备注
- 你的算法应该是一个线性时间复杂度。 你可以不用额外空间来实现它吗?
思路
- 位操作:一个数与自身做异或操作后未0,因此把这个数组中所有的元素依此求异或,剩下的就是多出来的。
- 暴力法:用一个set保存出现过的数字,如果存在就移除,最后剩下的就是唯一。
class Solution_136_01 {
public:
int singleNumber(vector& nums) {
if (nums.empty()) {
return -1;
}
int singleNum = 0;
for (auto iter = nums.begin(); iter != nums.end(); iter++) {
singleNum ^= *iter;
}
return singleNum;
}
};
//写一个暴力解法练手
class Solution_136_02 {
public:
int singleNumber(vector& nums) {
if (nums.empty()) {
return -1;
}
set numSet;
for (auto iter = nums.begin(); iter != nums.end(); iter++) {
if (numSet.count(*iter) == 1) {
numSet.erase(*iter);
} else {
numSet.insert(*iter);
}
}
return *numSet.begin();
}
};
350. 两个数组的交集 II
描述
- 给定两个数组,写一个方法来计算它们的交集。
例如
- 给定 nums1 = [1, 2, 2, 1], nums2 = [2, 2], 返回 [2, 2].
注意:
- 输出结果中每个元素出现的次数,应与元素在两个数组中出现的次数一致。
- 我们可以不考虑输出结果的顺序。
跟进
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
如果排过序,就能有规律所循。较小的那个数肯定不会再另一个容器总出现了,因此可以两个指针依次遍历来实现。 - 如果 nums1 的大小比 nums2 小很多,哪种方法更优?
一开始没什么思路,后面参考了下LeetCode,明白了出题者的意思。如果是基于排序算法,总体都是要遍历两个数组的,所以时间复杂度上是没有影响的,而此时的复杂度主要取决于排序算法本身。但如果是利用空间换时间,利用Map来实现的算法就完全不同了,此时时间复杂度是一定的max(O(n), O(m)),但空间复杂度是可变的,要选取更小的vector来构建辅助Map。
time complexity: max(O(m), O(n))
space complexity: choose one O(m) or O(n) <— So choose the smaller one if you can
- 如果 nums2的元素存储在磁盘上,内存是有限的,你不能一次加载所有的元素到内存中,你该怎么办?
不能一次性都加载进来,所以需要先排序,在遍历。参考LeetCode。
If only nums2 cannot fit in memory, put all elements of nums1 into a HashMap,read chunks of array that fit into the memory, and record the intersections.
If both nums1 and nums2 are so huge that neither fit into the memory, sort them individually (external sort), then read 2 elements from each array at a time in memory, record intersections.
思路
- 暴力法:什么都不考虑。直接拿一个元素去另一个vector中遍历,如果存在,则直接在另一个vector中删掉这个元素(太不科学的算法了)。
- 直观法:将一个数组的内容映射到一个Map中去,然后遍历另一个数组。
- 排序过:则直接两个指针从左到右遍历,谁小谁移动,一样就加入到结果中,然后一块移动。
Tips
- 多利用C++11的auto和“:”去遍历容器
- 该用const和&的位置要用
class Solution_350_01 {
public:
vector intersect(vector& nums1, vector& nums2) {
vector result;
if (nums1.empty() || nums2.empty()) {
return result;
}
map numMap;
vector& shortNum = nums1.size() < nums2.size() ? nums1 : nums2;
vector& longNum = shortNum == nums1 ? nums2 : nums1;
for (const auto num : shortNum) {
++numMap[num];
}
for (const auto num : longNum) {
if (numMap[num] > 0) {
result.push_back(num);
--numMap[num];
}
}
return result;
}
};
// 排序
class Solution_350_02 {
public:
vector intersect(vector& nums1, vector& nums2) {
vector result;
if (nums1.empty() || nums2.empty()) {
return result;
}
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
auto iter1 = nums1.begin();
auto iter2 = nums2.begin();
while (iter1 != nums1.end() && iter2 != nums2.end()) {
if (*iter1 < *iter2) {
++iter1;
} else if (*iter1 > *iter2) {
++iter2;
} else {
result.push_back(*iter1);
++iter1;
++iter2;
}
}
return result;
}
}