食用指南:
Leetcode专栏开启了,由于博主闭关期末,所以每日只能一题
尽量做到一题多解,先说思路,之后代码实现,会添加必要注释
语法或STL内容会在注意点中点出,新手友好
欢迎关注博主神机百炼专栏,内涵算法基础详细讲解和代码模板
题目描述:
-
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
-
代码背景:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
}
};
- 题目来源:https://leetcode.cn/problems/two-sum/
题目分析:
- 法一:暴力,双层循环,O(n2)
- 法二:单调双指针,排序O(nlogn),查找O(n)
注意排序之后打乱了原本序号和值的对应关系,需要使用pair<int, int>保存值 和 原本序号 - 法三:哈希表,插入一个元素O(1),查询一个元素O(1)
以nums[]值为索引,下标为值
算法模板:
代码实现:
- 双重循环O(n2) -> 耗时292ms
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
for(int i=0; i<nums.size()-1; i++){
for(int j=i+1; j<nums.size(); j++){
if(nums[i] + nums[j] == target){
return {i, j};
}
}
}
return {};
}
};
- 排序O(nlogn) + 单调双指针O(n) -> 耗时12ms
class Solution {
public:
void q_sort(vector<pair<int, int>>& nums, int l, int r){
if(l >= r) return;
int x = nums[(l + r)>>1].first;
int i = l-1, j = r+1;
while(i < j){
while(nums[++i].first < x);
while(nums[--j].first > x);
if (i < j) swap(nums[i], nums[j]);
}
q_sort(nums, l, j);
q_sort(nums, j+1, r);
}
vector<int> twoSum(vector<int>& arr, int target) {
vector<pair<int, int>> nums;
//注意pair<int, int> 保存原本值和序号对应关系
for(int i=0; i<arr.size(); i++){
nums.push_back({arr[i], i});
}
q_sort(nums, 0, nums.size()-1);
int i = 0, j = nums.size()-1;
//注意既不要冗余比较,又不要同点相加为target
while(i<j){
while(nums[i].first + nums[j].first > target) j--;
if(nums[i].first + nums[j].first == target)
return{nums[i].second, nums[j].second};
i++;
}
return {};
}
};
- 哈希表unordered_map<int>,总计O(2n) -> 耗时12ms
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
unordered_map<int , int> hash;
for(int i=0; i<nums.size(); i++){
hash[nums[i]] = i;
}
for(int i=0; i<nums.size(); i++){
if(hash.count(target - nums[i]) && hash[target-nums[i]] != i){
return {i, hash[target - nums[i]]};
}
}
return {};
}
};
注意点:
- vector<>的构相关函数:
- 普通创建:vector<int> nums;
- 赋值构造:vector<int> nums = {1,2,3,4};
- 拷贝构造:vector<int> nums2(nums);
- 指定表长构造:vector<int> nums(9); 长为9的空链表
- 指定元素重复构造:vector<int> nums(9, 3); 含有9个3的链表
- 插入元素:nums.push_back(1);
- pair<>的相关属性:
- pair相当于STL内置的一个结构体,含有两个元素
- pair<int ,int> point; 第一个元素为point.first; 第二个元素为point.second;
- sort() 默认以pair<>的first进行排序
- unordered_map<索引, 值>的相关操作:
- map本质是AVL树,unordered_map<索引, 值>本质是哈希表
- 创建哈希表:unordered_map<索引类型, 值类型> hash;
- 插入元素:hash[key] = value;
- 以key查询数量:hash,count(key);
- key对应值:hash[key];
- 对unordered_map<key. value>不太熟悉的同学看这里:状态压缩BFS