您的位置:首页 > 编程语言 > C语言/C++

two sum

2014-10-29 17:41 288 查看
Given an array of integers, find two numbers such that they add up to a specific target number.The function twoSum should return indices of the two numbers such that they
add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.

You may assume that each input would have exactly one solution.

Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2

*******************************************************************************************************
Anwer 1: O(n^2)
class Solution {
public:

vector<int> twoSum(vector<int> &numbers, int target) {
int len = numbers.size();
vector<int> results;
for(int i = 0; i < len - 1; i++) {
for(int j = i + 1; j < len; j++){
int sum = numbers[i] + numbers[j];
if(sum == target) {
results.push_back(i + 1);
results.push_back(j + 1);

return results;
}
}
}
}
};


Anwer 2: O(n*log(n)

class Solution {
public:

struct node {
/*bool operator > (const node& a) const {
return val > a.val;
}*/
bool operator < (const node& a) const {
return val <= a.val;
}
int idx; // record itself
int val;
};

// must use static to decorate
static bool cmp(const node *a, const node *b);

/*
since a, b in numbers, so if a + b == target,
so b = target - a
means that (target - a) must in numbers
so just iterately check target - numbers[i] is in numbers or not
here you can binary_search after sort the the copy of the numbers
*/
vector<int> twoSum(vector<int> &numbers, int target) {
// check
assert(numbers.size() >= 2);

vector<int> results;
vector<node> num;

int len = numbers.size();
for(int i = 0; i < len; i++) {
node temp;
temp.idx = i;
temp.val = numbers[i];
num.push_back(temp);
}

// ascending order -- use overload operator <
// also you can use cmp static function
sort(num.begin(), num.end());

int slen = num.size();
for(int i = 0; i < slen; i++) {
int dval = target - num[i].val;

int index = binary_search(num, dval, 0, slen - 1);

if(index != -1) {
int left = num[i].idx;
int right = num[index].idx;

if(left == right) {
continue;
}

if(left > right) {
swap(left, right);
}

// index: start from 1
results.push_back(left + 1);
results.push_back(right + 1);

break;
}
}

return results;
}

int binary_search(vector<node> &A, int target, int left, int right) {
while(left < right) {
int mid = (left + right) >> 1;

if(A[mid].val == target) {
return mid;
} else if(A[mid].val < target) {
left = mid + 1;
} else {
right = mid;
}
}

return -1;
}
};

bool Solution::cmp(const node *a, const node *b) {
return a->val < b->val;
}


Anwer 3: O(n*log(n))

class Solution {
public:

struct node {
/*bool operator > (const node& a) const {
return val > a.val;
}*/
bool operator < (const node& a) const {
return val <= a.val;
}
int idx; // record itself
int val;
};

// must use static to decorate
static bool cmp(const node *a, const node *b);

/*
since a, b in numbers, so if a + b == target,
so b = target - a
means that (target - a) must in numbers
so just iterately check target - numbers[i] is in numbers or not
here you can  after sort the the copy of the numbers
*/
vector<int> twoSum(vector<int> &numbers, int target) {
// check
assert(numbers.size() >= 2);

vector<int> results;
vector<node> num;

int len = numbers.size();
for(int i = 0; i < len; i++) {
node temp;
temp.idx = i;
temp.val = numbers[i];
num.push_back(temp);
}

// ascending order -- use overload operator <
// also you can use cmp static function
sort(num.begin(), num.end());

int slen = num.size();

int left = 0;
int right = slen - 1;
while(left < right) {
int sum = num[left].val + num[right].val;
if(sum == target) {
int lidx = min(num[left].idx, num[right].idx) + 1;
int ridx = max(num[left].idx, num[right].idx) + 1;

results.push_back(lidx);
results.push_back(ridx);

break;
} else if(sum < target) {
left++;
} else {
right--;
}
}

return results;
}

};

bool Solution::cmp(const node *a, const node *b) {
return a->val < b->val;
}


Anwer 4: O(n)

class Solution {
public:

/*
since a, b in numbers, so if a + b == target,
so b = target - a
means that (target - a) must in numbers
so just iterately check target - numbers[i] is in numbers or not
here you can  use map or pair
*/
vector<int> twoSum(vector<int> &numbers, int target) {
// check
assert(numbers.size() >= 2);

vector<int> results;
map<int, int> num;

int len = numbers.size();
for(int i = 0; i < len; i++) {
int diff = target - numbers[i];

// fist determine numbers[i] is visited or not
// and then insert it to map
if(num.find(numbers[i]) == num.end()){
num[numbers[i]] = i;
}

// second determine the diff (another numbers[j]) is in num or not
if(num.find(diff) != num.end()) {
int j = num[diff];

// some cases like this: numbers[i] + numbers[i] == target
if(i == j){
continue;
}

if(i > j) {
swap(i, j);

// result's index: start from 1
results.push_back(i + 1);
results.push_back(j + 1);
break;
}
}
}

return results;
}

};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++