(写给未来遗忘的自己)
1.暴力破解法
直接两个for循环,直接加
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target)
{
int n = nums.size();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j < n; ++j) {
if (nums[i] + nums[j] == target) {
return {i, j};
}
}
}
return {};
}
};
2.利用std::undered_map来计算
class Solution {
public:
std::vector<int> twoSum(std::vector<int>& nums, int target) {
std::unordered_map<int, int> indexMap;
std::vector<int> result;
for (int i = 0; i < nums.size(); ++i) {
int complement = target - nums[i];
auto it = indexMap.find(complement);
if (it != indexMap.end()) {
// 找到匹配的元素
result.push_back(it->second);
result.push_back(i);
return result;
}
indexMap[nums[i]] = i;
}
// 如果没有找到匹配的元素,可以抛出异常或返回一个错误状态
throw std::runtime_error("No two sum solution");
}
};
使用同样的map类型的哈希数表,map的三种具体实现写在文末。
思路:
1.我直到结果target,那我在遍历到的值知道,相当于查找一个差值是否存在,当用到查找的时候就考虑哈希数表(数组,set,map) std::undered_map 的查找和删除复杂度O(1)。
2.将遍历过的值作为key,下标作为值存储。当前值和遍历过存储的值中寻找是否有满足的。std::undered_map的Key不允许重复,尽管例如[3,3],当遍历nums[1]的时候,其还没有放进去,所以不影响。
#一个错误的方法 std::multiset
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
std::multiset<int>nums_set(nums.begin(),nums.end());
vector<int>input;
int table=0;
int two_num,one_num;
for(int num:nums_set ){
two_num=target-num;
one_num=num;
if(nums_set.find(two_num)!=nums_set.end()){
table=1;
break;
}
}
if(table==1){
for(int j=0;j<nums.size();j++)
{
if(nums[j]==one_num){
input.push_back(j);
}
if(nums[j]==two_num){
input.push_back(j);
}
if(input.size()==2){
break;
}
}
}
return input;
}
};
原因:一开始选择的原因是 哈希数表的查询速度快,另外两种set都不允许重复的数,这个允许。
但是存在关键问题:
-
使用
std::multiset
会改变原始数组的顺序,因此你不能直接从multiset
中找到原始数组中的索引。(所以需要找到数后继续回去vector里面找下标) -
在查找匹配项时,没有检查是否使用了相同的元素两次(即
one_num
和two_num
是否在原数组中为同一位置的元素)。 -
当找到匹配对时,循环可能不会正确地返回第一个匹配对的索引,因为
std::multiset
不保证保持元素的插入顺序。(这个就是第一个的附带问题)
———————————————————————————————————————————map的使用方法:
1. std::map
- 数据结构:基于红黑树,键值对是有序的。(根据键的值排序的,由于使用的红黑树,所以可以二分查找)
- 插入操作:如果键已存在,插入失败,不会覆盖已存在的键值对。
- 查找效率:对数时间复杂度(O(log n)),因为树的结构。
- 迭代器:提供稳定且连续的迭代器,可以按升序遍历键值对
-
std::map<std::string, int> myMap; myMap["apple"] = 1; myMap["banana"] = 2;
2.
std::unordered_map
- 数据结构:基于哈希表,键值对是无序的(哈希表通过计算键的哈希值来确定键值对的存储位置)。
- 插入操作:如果键已存在,插入失败,但如果使用
insert
方法并提供一个键值对,可以设置是否覆盖已存在的值。 - 查找效率:平均情况下的常数时间复杂度(O(1)),但最坏情况是线性的(O(n)),取决于哈希函数和冲突处理策略。
- 迭代器:不保证迭代器的稳定性,因为元素的位置可能由于重新哈希而变化。
std::unordered_map<std::string, int> myUnorderedMap;
myUnorderedMap["apple"] = 1;
myUnorderedMap["banana"] = 2;
3. std::multimap
- 数据结构:与
std::map
类似,基于红黑树,键值对是有序的。 - 插入操作:允许同一个键有多个值,形成键值对的集合。
- 查找效率:对数时间复杂度(O(log n)),与
std::map
相同。 - 迭代器:提供稳定且连续的迭代器,可以按升序遍历键值对。
std::multimap<std::string, int> myMultimap;
myMultimap.insert({"apple", 1});
myMultimap.insert({"apple", 2});
myMultimap.insert({"banana", 3});