都用哈希表的方法
两数之和
vector<int> twoSum(vector<int>& nums, int target) {
int s;
unordered_map<int,int> map;
for(int k = 0; k < nums.size();k++)
{
map[nums[k]] = k;
}
for(int i = 0; i < nums.size(); i++)
{
s = target - nums[i];
if(map.count(s) != 0 && map[s] != i)
return {i,map[s]};
}
}
利用unordered_map储存nums的哈希映射关系,map利用数组的方式储存,相同关键字冲突时,后者可以覆盖前者。
遍历时利用target-nums[i]找到对应地址。
unordered_map和map的区别
map:
- 优点:
- 有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
- 红黑树,内部实现一个红黑书使得map的很多操作在
lgn
的时间复杂度下就可以实现,因此效率非常的高
-
缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间
-
适用处:对于那些有顺序要求的问题,用map会更高效一些
unordered_map:
- 优点: 因为内部实现了哈希表,因此其查找速度非常的快
- 缺点: 哈希表的建立比较耗费时间
- 适用处:对于查找问题,
unordered_map
会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map
总结:
1. 内存占有率的问题就转化成红黑树 VS hash表 , 还是unorder_map占用的内存要高。
2. 但是unordered_map执行效率要比map高很多
3. 对于unordered_map
或unordered_set
容器,其遍历顺序与创建该容器时输入的顺序不一定相同,因为遍历是按照哈希表从前往后依次遍历的
三数之和
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> Sum;
sort(nums.begin(),nums.end());
if(nums.empty() || nums[0] > 0 || nums.back() < 0)
return {};
for(int i = 0; i < nums.size(); i++)
{
if(nums[i] > 0)
break;
if(i > 0 && nums[i] == nums[i-1])
continue;
int m = i+1, n = nums.size()-1;//m = i.next; n = nums.final
while(m < n)
{
if(nums[m] + nums[n] + nums[i] ==0)
{
Sum.push_back({nums[i], nums[m], nums[n]});
m++;
n--;
while(m < n && nums[m] == nums [m-1])
m++;
while(m < n && nums[n] == nums[n+1])
n--;
}
else if(nums[m] + nums[n] + nums[i] > 0)
n--;
else
m++;
}
}
return Sum;
}
先将nums排序,建立哈希表
确定一个值,寻找另外两个值时,从最近和最远逐步向中间靠拢,越靠近头部越小,越靠近尾部越大。
最接近的三数之和
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int k,sum,m,n;
sort(nums.begin(),nums.end());
k = nums[0] + nums[1] + nums[nums.size() - 1];
for(int i = 0; i < nums.size(); i++)
{
m = i + 1;
n = nums.size() - 1;
while(m < n)
{
sum = nums[i] + nums[m] + nums[n];
if(abs(k - target) >= abs(sum - target))
{
k = sum;
}
if(sum < target)
m++;
else if(sum > target)
n--;
else
return k;
}
}
return k;
}
};