Day2
03.01.03 练习题目(第 02 天)
1. 0349. 两个数组的交集
1.1 题目大意
描述:给定两个数组 nums1
和 nums2
。
要求:返回两个数组的交集。重复元素只计算一次。
说明:
- 1 ≤ n u m s 1. l e n g t h , n u m s 2. l e n g t h ≤ 1000 1 \le nums1.length, nums2.length \le 1000 1≤nums1.length,nums2.length≤1000。
- 0 ≤ n u m s 1 [ i ] , n u m s 2 [ i ] ≤ 1000 0 \le nums1[i], nums2[i] \le 1000 0≤nums1[i],nums2[i]≤1000。
示例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[9,4]
解释:[4,9] 也是可通过的
我的答案
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> set1;
unordered_set<int> set2;
vector<int> ans;
for(int n : nums1){
set1.insert(n);
}
for(int n : nums2){
set2.insert(n);
}
for(int n: set2){
if(set1.count(n)){
ans.push_back(n);
}
}
return ans;
}
};
其他答案:
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
unordered_set<int> set1(nums1.begin(), nums1.end()); //赋值方式
vector<int> ans;
for (int n : nums2) {
if (set1.erase(n)) { // 巧妙的处理方式,能够被擦除,说明存在
ans.push_back(n);
}
}
return ans;
}
};
//排序 + 双指针
class Solution {
public:
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
vector<int> ans;
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
int i = 0, j = 0;
while (i < nums1.size() && j < nums2.size()) {
if (nums1[i] == nums2[j]) {
if (ans.empty() || ans.back() != nums1[i]) {
ans.push_back(nums1[i]);
} // 这个条件设计很巧妙,去重。
i++;
j++;
} else if (nums1[i] < nums2[j]) {
i++;
} else {
j++;
}
}
return ans;
}
};
2. 0350. 两个数组的交集 II
2.1 题目大意
描述:给定两个数组 nums1
和 nums2
。
要求:返回两个数组的交集。可以不考虑输出结果的顺序。
说明:
- 输出结果中,每个元素出现的次数,应该与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。
- 1 ≤ n u m s 1. l e n g t h , n u m s 2. l e n g t h ≤ 1000 1 \le nums1.length, nums2.length \le 1000 1≤nums1.length,nums2.length≤1000。
- 0 ≤ n u m s 1 [ i ] , n u m s 2 [ i ] ≤ 1000 0 \le nums1[i], nums2[i] \le 1000 0≤nums1[i],nums2[i]≤1000。
示例:
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2,2]
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]
我的答案:
//占很多步骤还可以优化
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int,int>map1;
unordered_map<int,int>map2;
vector<int> ans;
for(int i = 0;i<nums1.size();++i){
map1[nums1[i]] ++;
}
for(int i = 0;i<nums2.size();++i){
map2[nums2[i]] ++;
}
for(auto i : map1){
if(map1[i.first]&&map2[i.first]){
int tmp = min(map1[i.first],map2[i.first]);
while(tmp--){
ans.push_back(i.first);
}
}
}
return ans;
}
};
其他答案:
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
unordered_map<int, int> counts;
vector<int> result;
// 计算nums1中每个数字的出现次数
for (int num : nums1) {
counts[num]++;
}
// 遍历nums2,如果数字在counts中存在,则添加到结果中,并减少counts中的计数
for (int num : nums2) {
if (counts[num] > 0) {
result.push_back(num);
counts[num]--;//有一个一样,就相当于消掉了。
}
}
return result;
}
};
//排序 + 双指针
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
vector<int> result;
int i = 0, j = 0;
while (i < nums1.size() && j < nums2.size()) {
if (nums1[i] < nums2[j]) {
++i;
} else if (nums1[i] > nums2[j]) {
++j;
} else {
result.push_back(nums1[i]);
++i;
++j;
}
}
return result;
}
};
3. 0706. 设计哈希映射
3.1 题目大意
要求:不使用任何内建的哈希表库设计一个哈希映射(HashMap
)。
需要满足以下操作:
MyHashMap()
用空映射初始化对象。void put(int key, int value) 向 HashMap
插入一个键值对(key, value)
。如果key
已经存在于映射中,则更新其对应的值value
。int get(int key)
返回特定的key
所映射的value
;如果映射中不包含key
的映射,返回-1
。void remove(key)
如果映射中存在 key 的映射,则移除key
和它所对应的value
。
说明:
- 0 ≤ k e y , v a l u e ≤ 1 0 6 0 \le key, value \le 10^6 0≤key,value≤106。
- 最多调用
1
0
4
10^4
104 次
put
、get
和remove
方法。
示例:
输入:
["MyHashMap", "put", "put", "get", "get", "put", "get", "remove", "get"]
[[], [1, 1], [2, 2], [1], [3], [2, 1], [2], [2], [2]]
输出:
[null, null, null, 1, -1, null, 1, null, -1]
解释:
MyHashMap myHashMap = new MyHashMap();
myHashMap.put(1, 1); // myHashMap 现在为 [[1,1]]
myHashMap.put(2, 2); // myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(1); // 返回 1 ,myHashMap 现在为 [[1,1], [2,2]]
myHashMap.get(3); // 返回 -1(未找到),myHashMap 现在为 [[1,1], [2,2]]
myHashMap.put(2, 1); // myHashMap 现在为 [[1,1], [2,1]](更新已有的值)
myHashMap.get(2); // 返回 1 ,myHashMap 现在为 [[1,1], [2,1]]
myHashMap.remove(2); // 删除键为 2 的数据,myHashMap 现在为 [[1,1]]
myHashMap.get(2); // 返回 -1(未找到),myHashMap 现在为 [[1,1]]
我的答案:
class MyHashMap {
vector<int> map;
int size = 1000001;
public:
MyHashMap() {
map.resize(size,-1);
}
void put(int key, int value) {
map[key] = value;
}
int get(int key) {
return map[key];
}
void remove(int key) {
map[key] = -1;
}
};
其他答案:
//链地址法
#include <list>
#include <vector>
class MyHashMap {
private:
const int BUCKET_SIZE = 769; // 选择一个合适的桶大小以减少冲突
vector<list<pair<int, int>>> buckets;
public:
MyHashMap() {
buckets.resize(BUCKET_SIZE); // 初始化桶的数量
}
int hash(int key) {
return key % BUCKET_SIZE; // 简单的哈希函数
}
list<pair<int, int>>& getBucket(int key) {
return buckets[hash(key)]; // 获取键对应的桶
}
pair<int, int>* findPair(list<pair<int, int>>& bucket, int key) {
for (auto it = bucket.begin(); it != bucket.end(); ++it) {
if (it->first == key) {
return &(*it); // 如果找到了键,返回键值对的指针
}
}
return nullptr; // 如果没有找到键,返回 nullptr
}
void put(int key, int value) {
int bucketIndex = hash(key);
list<pair<int, int>>& bucket = getBucket(key);
pair<int, int>* pair = findPair(bucket, key);
if (pair) {
pair->second = value; // 如果键已经存在,更新值
} else {
bucket.push_back(make_pair(key, value)); // 如果键不存在,添加新的键值对
}
}
int get(int key) {
int bucketIndex = hash(key);
list<pair<int, int>>& bucket = getBucket(key);
pair<int, int>* pair = findPair(bucket, key);
return pair ? pair->second : -1; // 如果找到了键,返回值;否则返回 -1
}
void remove(int key) {
int bucketIndex = hash(key);
list<pair<int, int>>& bucket = getBucket(key);
auto it = bucket.begin();
while (it != bucket.end()) {
if (it->first == key) {
bucket.erase(it); // 如果找到了键,从链表中移除键值对
return;
}
++it;
}
}
};