代码随想录 哈希表-8
中等
给你一个包含
n
个整数的数组nums
,判断nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为0
且不重复的三元组。注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]示例 2:
输入:nums = [] 输出:[]示例 3:
输入:nums = [0] 输出:[]
方法1:自己尝试
千辛万苦勉强能跑,但是时间复杂度太高了,能通过225/331个样例,牛客网能通过24/25个样例(最后是因为空间超了)。麻了,大体思路是跟两数之和和四数之和差不多,先遍历一遍求出两个数的和,存放在哈希表mp和mp_index里(还得存两个哈希表,两个哈希表的key都是两数的和,value一个存数值,另一个存下标),最后再遍历一遍找mp中有无key 为每个元素的相反数的,如果有,插入到最后的result。(在插入Result 时也有很多细节问题,比如 vector不能vector.find,只能find(vector.begin(),vector.end(),k), 再比如提取vector倒数第二个元素需要用*(vector.end()-2) ,.end() 返回终止迭代器,-2 以后返回的还是迭代器,得取*才能取回元素。等等)
可惜的是最后也没有完全通过,搞了2个半小时,不过也挺有进步的。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
// 自己尝试,2022年7月20日 16点55分--17:43 没做出来----19:00继续做--20:49 d大概能通过了,就是时间复杂度太高
// 暴力解,先两重for 遍历填满两数和,再找第三个数
// 哈希表key是两数和,value 存两个值(多个值,可能不只两对)
unordered_map<int, vector<int>> mp;
unordered_map<int, vector<int>> mp_index;
for(int i = 0; i < nums.size(); i++){
for(int j = i + 1; j < nums.size(); j++){
mp[nums[i] + nums[j]].push_back(nums[i]);
mp[nums[i] + nums[j]].push_back(nums[j]);
mp_index[nums[i] + nums[j]].push_back(i);
mp_index[nums[i] + nums[j]].push_back(j);
}
}
vector<vector<int>> result;
for(int k = 0; k < nums.size(); k++){
auto it = mp.find(-nums[k]);
if(it != mp.end()){
// 还得保证 nums[k] 与之前两个数不重复----不对,是之前两个下标
auto it_index = mp_index.find(-nums[k]);
vector<int> sum_index = it_index->second;
// 注意:vector不能用 vector.find,因为find不是vector的属性
// 而是 vector 的函数,只可以 find(vector.begin(),vector.end(),3)
// find(sum.begin(),sum.end(),nums[k]) == sum.end()
// cout <<"和为:"<< it->first << ": {";
// for(int nuu : it->second){
// cout << nuu <<" ";
// }
// cout <<"}" << "下标为:{";
// for(int nnu : sum_index){
// cout << nnu <<" ";
// }
// cout <<"}" <<endl;
while(!it->second.empty()){
//nums[k] 与数组最后两个数[的下标]不重复,插入
if(find(sum_index.end()-2,sum_index.end(),k) == sum_index.end()){
vector<int> tmp;
tmp.push_back(nums[k]);
//从后面插两个再删掉最后两个,直到没了
tmp.push_back(it->second.back());
// 倒数第二个,必须用end()-2,然后用*取值
tmp.push_back(*(it->second.end()-2));
result.push_back(tmp);
}
it->second.pop_back();
it->second.pop_back();
// sum_index 也得pop_back---第二次提交的错误发现
sum_index.pop_back();
sum_index.pop_back();
}
// //删除结果中的重复元素
// for(int m = 0; m < result.size(); m++){
// vector<int> tmp1 = result[m];
// sort(tmp1.begin(),tmp1.end());
// for(int n = m+1; n < result.size(); n++){
// vector<int> tmp2 = result[n];
// sort(tmp2.begin(),tmp2.end());
// if(tmp1 == tmp2){
// result.erase(result.begin() + n);
// n--;
// }
// }
// }
// 用set 来删除重复元素会不会快一点
for(int m = 0; m < result.size(); m++){
unordered_set<int> set1(result[m].begin(),result[m].end());
for(int n = m+1; n < result.size(); n++){
unordered_set<int> set2(result[n].begin(),result[n].end());
if(set1 == set2){
result.erase(result.begin() + n);
n--;
}
}
}
// for(vector<int> out_res : result){
// cout << "[";
// for(int in_res: out_res){
// cout<< in_res <<", ";
// }
// cout << "],";
// }
// cout <<endl;
}
}
// //最后再删一下结果中的重复元素
// for(int m = 0; m < result.size(); m++){
// vector<int> tmp1 = result[m];
// sort(tmp1.begin(),tmp1.end());
// for(int n = m+1; n < result.size(); n++){
// vector<int> tmp2 = result[n];
// sort(tmp2.begin(),tmp2.end());
// if(tmp1 == tmp2){
// result.erase(result.begin() + n);
// // erase后result.size()会减1,所以n 也得减,
// // 测试用例222 [3,0,3,2,-4,0,-3,2,2,0,-1,-5] 发现
// n--;
// }
// }
// }
// // 用set 来删除重复元素会不会快一点
// for(int m = 0; m < result.size(); m++){
// unordered_set<int> set1(result[m].begin(),result[m].end());
// for(int n = m+1; n < result.size(); n++){
// unordered_set<int> set2(result[n].begin(),result[n].end());
// if(set1 == set2){
// result.erase(result.begin() + n);
// n--;
// }
// }
// }
return result;
}
};