一、问题描述:
Given an arrayof integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution.
Example:
Given nums = [2, 7,11, 15], target = 9,
Because nums[0]+ nums[1] = 2 + 7 = 9,
return [0, 1].
给出一组整数nums,在其中找出相加和为target,返回其下标。
二、 解题思路:
a) 创建结构体IV,将输入的nums映射为myIV[],对myIV进行排序。
struct IV {
int id;//index
int val;//value
IV() {}//没有此构造函数在创建IV类型的指针或数组时会报错
IV(int i, int v) {
this->id= i;
this->val= v;
}
bool operator<(const IV& a)const{//重载运算符<用于sort(),注意此处只能重载 < 而不能重载 > !长时间不用C++都忘记了= =
returnthis->val < a.val;
}
};
b) 对排序后的myIV进行遍历,对于每个元素调用函数findIndex()来查找与其匹配的元素下标。采用方法为二分查找(由于数组中元素已经排序过了)。
intSolution::findIndex(IV *&iv, int left, int right, int target) {
if (left >right) {
return -1;
}
int mid =(right+left)/2;
if (iv[mid].val ==target) {
return mid;
}
else if(iv[mid].val < target) {
return findIndex(iv, mid+1, right, target);
}
else {
return findIndex(iv, left, mid-1, target);
}
}
三、源代码
#include<iostream>
#include<vector>
#include<iterator>
#include<algorithm>
#include<unordered_map>
using namespacestd;
class Solution {
public:
vector<int>TwoSum(vector<int>& nums, int target);
private:
struct IV {
int id;
int val;
IV() {}
IV(int i, int v) {
this->id = i;
this->val = v;
}
bool operator<(const IV&a) const{
return this->val< a.val;
}
};
int findIndex(IV *&iv, int left,int right, int target);
};
intSolution::findIndex(IV *&iv, int left, int right, int target) {
if (left > right) {
return -1;
}
int mid = (right+left)/2;
if (iv[mid].val == target) {
return mid;
}
else if (iv[mid].val < target) {
return findIndex(iv, mid+1,right, target);
}
else {
return findIndex(iv, left,mid-1, target);
}
}
vector<int>Solution::TwoSum(vector<int>& nums, int target) {
IV* myIV = new IV[nums.size()];
for (int i = 0; i < nums.size();++i) {
myIV[i] = IV(i, nums[i]);
}
sort(myIV, myIV+nums.size());
for (int i = 0; i < nums.size();++i) {
int tmpPos = findIndex(myIV,i+1, nums.size()-1, target-myIV[i].val);
if (tmpPos!=-1) {
vector<int> ans;
ans.push_back(myIV[i].id);
ans.push_back(myIV[tmpPos].id);
delete[] myIV;
return ans;
}
}
delete[] myIV;
}
int main(int argc,char const *argv[]) {
vector<int> nums;
nums.clear();
int target;
while(cin >> target) {
nums.push_back(target);
}
nums.pop_back();
Solution s;
vector<int> ans = s.TwoSum(nums,target);
for(std::vector<int>::const_iterator i = ans.begin(); i != ans.end(); ++i) {
cout << *i<<",";
}
return 0;
}
四、 分析:
a) 在TwoSum()中的遍历过程中加入&&myIV[i].val < target/2+1作为结束条件,效率反倒不如不加,这是因为题目保证一定有解的缘故吧。但当不保证一定有解的情况可以提高一定效率。
b) 该方法实际上可由ordered_map代替。
ordered_map不会根据key的大小进行排序,存储时是根据key的hash值判断元素是否相同,即unordered_map内部元素是无序的,而map中的元素是按照二叉搜索树存储,进行中序遍历会得到有序遍历。所以使用时map的key需要定义operator<。而unordered_map需要定义hash_value函数并且重载operator==。但是很多系统内置的数据类型都自带这些,那么如果是自定义类型,那么就需要自己重载operator<或者hash_value()了。
结论:如果需要内部元素自动排序,使用map,不需要排序使用unordered_map。
本题代码:
class Solution {
public:
vector<int>twoSum(vector<int>& nums, int target) {
map<int, int> m;
for(int i = 0; i < nums.size(); i++)
{
if(m.find(target-nums[i]) !=m.end())
return {m[target-nums[i]], i};
m[nums[i]] = i;
}
}
};
map还不如ordered_map效率高…
五、总结:
时隔好久再摸C++,好多东西都忘记了,若不是准备MS等公司的机试,什么指针引用操作符重载都忘得干干净净了…虽然这道题目比较简单,但还是温习了不少知识点,而且感觉如果时间空间允许用内置容器方法是个很不错的选择,但是显然这道题目自己构造结构体效率高很多hhh。