350.两个数组的交集
方法一:排序+双指针
sort(nums1.begin(), nums1.end());
sort(nums2.begin(), nums2.end());
自己想到了一半,☞排序。双指针没有用好,还是只会暴力for循环。
注意是数组,不是集合。
初始时,两个指针分别指向两个数组的头部。
每次比较两个指针指向的两个数组中的数字,如果两个数字不相等,则将指向较小数字的指针右移一位。
如果两个数字相等,将该数字添加到答案,并将两个指针都右移一位。
当至少有一个指针超出数组范围时,遍历结束。
int i=0,j=0;
while( i<nums1.size()&&j<nums2.size()){
if(nums1[i]==nums2[j]){
nums.push_back(nums1[i]);
i++;j++;
}else if(nums1[i]<nums2[j])
{
i++;
}else{
j++;
}
}
方法二:哈希表(完全没想到属于是)
由于同一个数字在两个数组中都可能出现多次,因此需要用哈希表存储每个数字出现的次数。
对于一个数字,其在交集中出现的次数等于该数字在两个数组中出现次数的最小值。
首先遍历第一个数组,并在哈希表中记录第一个数组中的每个数字以及对应出现的次数。
然后遍历第二个数组,对于第二个数组中的每个数字,如果在哈希表中存在这个数字,则将该数字添加到答案,并减少哈希表中该数字出现的次数。
为了降低空间复杂度,首先遍历较短的数组并在哈希表中记录每个数字以及对应出现的次数,然后遍历较长的数组得到交集。
class Solution {
public:
vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
if (nums1.size() > nums2.size()) {
return intersect(nums2, nums1);
}
unordered_map <int, int> m;
for (int num : nums1) {
++m[num]; //对应的次数+1
}
vector<int> nums;
for (int num : nums2) {
if (m.count(num)) {
nums.push_back(num);
--m[num]; //对应的次数-1
if (m[num] == 0) {
m.erase(num);
}
}
}
return nums;
}
};
哈希表的成员函数:
empty():判断容器是否为空。
size():返回unordered_map中的元素数量。
max_size():容器可以容纳的最大元素数量。
find():获取元素的迭代器。在容器中搜索以k为键的元素,如果找到则返回一个迭代器,否则返回一个迭代器到unordered_map::end(容器末尾的元素)。
count():查找具有特定键的元素的数量
在容器中搜索键为k的元素并返回找到的元素数。因为unordered_map容器不允许重复键,这意味着如果容器中存在具有该键的元素,则该函数实际上返回1 ,否则返回 0。
insert():在unordered_map中插入新元素。
只有当每个元素的键不等于容器中已经存在的任何其他元素的键时,才会插入每个元素(unordered_map中的键是唯一的)。这通过插入的元素数量有效地增加了容器大小。
unordered_map 模板类中,提供了多种语法格式的 insert() 方法,根据功能的不同,可划分为以下几种用法。
erase():从unordered_map容器中删除单个元素或一系列元素([first,last))。
这有效地通过删除元素的数量来减小容器大小,调用每个元素的析构函数。
clear():清除unordered_map容器中的所有元素。
121.买卖股票的最佳时机(为什么我的暴力法超时了,解答的暴力就行啊,真的救命)
方法二:
假如计划在第 i 天卖出股票,那么最大利润的差值一定是在[0, i-1] 之间选最低点买入;
所以遍历数组,依次求每个卖出时机的的最大差值,再从中取最大值。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int inf = 1e9;
int minprice = inf, maxprofit = 0;
for (int price: prices) {
maxprofit = max(maxprofit, price - minprice);
minprice = min(price, minprice);
}
return maxprofit;
}
};