题目链接:初级算法 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
思路一: 第一想法当然使用两张表存储两个数组中数字出现的次数啦(这道题的数组范围都比较小),然后遍历表得到次数的最小值,就可以加入到结果中了,不过这样的时空复杂度较大。
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> hash1(1001, 0), hash2(1001, 0);
vector<int> ret;
for (auto x:nums1) hash1[x]++;
for (auto x:nums2) hash2[x]++;
for (int i = 0; i < 1001; i++) {
int mn = min(hash1[i], hash2[i]);
while(mn--) {
ret.push_back(i);
}
}
return ret;
}
};
思路二:既然想到用哈希表了,那有没有更加简单的写法呢?当然有了(看注释即可)!
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
vector<int> ret;
map<int, int> mp; // 哈希表记录nums1中各个数字出现的次数
for (auto x: nums1) mp[x]++;
for (auto x: nums2) {
if (mp[x]) { // 如果出现在mp表中
ret.push_back(x); // 加入到结果中
if(!mp[x]--) { // 为保证是最小的次数,每次都要--并且判断是否为0
mp.erase(x); // 若为0,可以直接剔除
}
}
}
return ret;
}
};
题解思考:看完题解,发现对于有序数组可以采用双指针的方法,还是可以理解的。
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
vector<int> ret;
int index1 = 0, index2 = 0; // 初始时指针都指向0
while (index1 < nums1.size() && index2 < nums2.size()) {
// nums_i[index_i]小的说明在另一个数组中不存在,或者是上一个检查过的重复的个数较少的元素
if (nums1[index1] < nums2[index2]) {
index1++;
}
else if (nums1[index1] > nums2[index2]) {
index2++;
}
else {
// 如果相同,那么就可以直接加入ret,且对于同一个元素加入的次数就是两者并集中该元素的个数
ret.push_back(nums1[index1]);
index1++;
index2++;
}
}
return ret;
}
};