(0) Two Sum (注,这道题最后才发现,所以坐标从0开始)
一开始看觉得好简单直接遍历所有可能不就好了吗,O(n*n)。
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> ret;
int i,j,n=numbers.size();
if(n<2)
return ret;
for(i=0;i<n-1;i++)
{
j=i+1;
while(j<n){
if(numbers[i]+numbers[j]==target)
{
ret.push_back(i+1);
ret.push_back(j+1);
return ret;
}
j++;
}
}
}
结果 Time Limit Exceeded。 果然n太大时会超时。
想了想觉得(1)的那种首尾指针时间复杂度会减少(O(nlogn)+O(n)=O(nlogn)),但是这个需要输出坐标的,如果排序之后坐标怎么保存呢,后来搜了搜参考了[4],巧妙利用了sort()函数第三个可定义判断条件的参数,还需自己新建一个结构体同时保存原来的值和坐标,结构体排序后保持对应不变。
typedef struct node{
int val;
int pos;
}Node;
bool compare(Node a, Node b){
return a.val<=b.val;
}
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> ret;
int i,j,n=numbers.size(),sum;
vector<Node> tmp(n);
if(n<2)
return ret;
for(i=0;i<n;i++){
tmp[i].val=numbers[i];
tmp[i].pos=i+1;
}
sort(tmp.begin(),tmp.end(),compare);
i=0;j=n-1;
while(i<j){
sum=tmp[i].val+tmp[j].val;
if(sum==target)
{
ret.push_back(min(tmp[i].pos,tmp[j].pos));
ret.push_back(max(tmp[i].pos,tmp[j].pos));
return ret;
}
else if(sum<target)
i++;
else j--;
}
}
};
Accepted(48ms)。
class Solution {
public:
vector<int> twoSum(vector<int> &numbers, int target) {
vector<int> result;
map<int,int> mapping;
for (int i=0; i<numbers.size(); ++i)
{
if (mapping[ target - numbers[i]] > 0)
{
result.push_back(mapping[ target - numbers[i]]);
result.push_back(i+1);
}
else
mapping[ numbers[i] ] = i+1;
}
return result;
}
};
Accepted(103ms)。时间反而长了,可能是因为对map的处理(查找,插入)占了比较大的开销。
(1) 3sum
这是一道求三个数为固定值的题,参考到了编程之美中快速寻找符合条件的两个数或者三个数[1]的算法:
先用快速排序对数组排序,让后用双指针(双索引)法对排序好的数组进行反向遍历,并且遍历的方向不变。(若是计算两个数的和,则初始化为i=0,j=n-1,若是计算两个数的差,则初始化为i=0,j=1)。之所以这样遍历方式能成功,是因为排序后,若ai+aj<sum,则ai+ak<sum(k=i,i+1...j),而i之前j之后的情况已遍历过,所以只有i++才可能有等号的情况;若ai+aj>sum,则ak+aj>sum(k=i,i+1...j),而i之前j之后的情况已遍历过,所以只有j--才可能有等号的情况。时间复杂度为O(nlogn)+O(n*n)=O(n*n)。
然后就唰唰唰写下第一个版本:
class Solution { //version 1.0
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int>> ret;
int i,j,k,n=num.size(),sum;
sort(num.begin(),num.end());
if(n<=2)
return ret;
for( k=0;k<n;k++){
sum=0-num[k];
i=k+1;
j=n-1;
if(i==j)
break;
while(i<j){
if(num[i]+num[j]==sum)
{
vector<int> tmp;
tmp.push_back(num[i]);
tmp.push_back(num[j]);
tmp.push_back(num[k]);
ret.push_back(tmp);
i++;
j--;
}
else if(num[i]+num[j]<sum)
i++;
else
j--;
}
}
return ret;
}
};
结果提示:
Output Limit Exceeded
后来网上搜了一通参考到[2],才明白我的输出包含相同的例子,所以输出非常多导致时间超了。
然后改了改...
class Solution { //version 2.0
public:
vector<vector<int> > threeSum(vector<int> &num) {
vector<vector<int>> ret;
int i,j,k,n=num.size(),sum;
sort(num.begin(),num.end());
if(n<=2)
return ret;
for( k=0;k<n;k++){
if(k > 0 && num[k]==num[k-1]) //过滤相同的k
continue;
sum=0-num[k];
i=k+1;
j=n-1;
if(i==j)
break;
while(i<j){
if(i>k+1&&num[i]==num[i-1]){ //过滤相同的i
i++;
continue;
}
if(j<num.size()-1&& num[j]==num[j+1]){ //过滤相同的j
j--;
continue;
}
if(num[i]+num[j]==sum)
{
vector<int> tmp;
tmp.push_back(num[k]);
tmp.push_back(num[i]);
tmp.push_back(num[j]);
ret.push_back(tmp);
i++;
j--;
}
else if(num[i]+num[j]<sum)
i++;
else
j--;
}
}
return ret;
}
};
Accepted (254ms)!!!
class Solution {
public:
int threeSumClosest(vector<int> &num, int target) {
int i,j,k,n=num.size(),sum,ret,flag=true;
sort(num.begin(),num.end());
if(n<=2)
return 0;
ret=num[0]+num[1]+num[2]; //ret初始值
for( k=0;k<n;k++){
if(k > 0 && num[k]==num[k-1]) //过滤相同的k
continue;
i=k+1;
j=n-1;
if(i==j)
break;
while(i<j){
if(i>k+1&&num[i]==num[i-1]){ //过滤相同的i
i++;
continue;
}
if(j<num.size()-1&& num[j]==num[j+1]){ //过滤相同的j
j--;
continue;
}
sum=num[i]+num[j]+num[k];
if(abs(sum-target)<abs(ret-target))
ret=sum;
if(sum==target)
return target;
else if(sum<target)
i++;
else
j--;
}
}
return ret;
}
};
Accepted (54ms)!!!
(3) 4sumclass Solution {
public:
vector<vector<int> > fourSum(vector<int> &num, int target) {
vector<vector<int>> ret;
int i,j,k,l,n=num.size(),sum;
sort(num.begin(),num.end());
if(n<4)
return ret;
for(l=0;l<=n-4;l++){
if(l > 0 && num[l]==num[l-1]) //过滤相同的l
continue;
for( k=l+1;k<=n-3;k++){
if(k > l+1 && num[k]==num[k-1]) //过滤相同的k
continue;
sum=target-num[l]-num[k];
i=k+1;
j=n-1;
if(i==j)
break;
while(i<j){
if(i>k+1&&num[i]==num[i-1]){ //过滤相同的i
i++;
continue;
}
else if(j<num.size()-1&& num[j]==num[j+1]){ //过滤相同的j
j--;
continue;
}
else if(num[i]+num[j]==sum)
{
vector<int> tmp;
tmp.push_back(num[l]);
tmp.push_back(num[k]);
tmp.push_back(num[i]);
tmp.push_back(num[j]);
ret.push_back(tmp);
i++;
j--;
}
else if(num[i]+num[j]<sum)
i++;
else
j--;
}
}
}
return ret;
}
};
Accepted (454ms)!!!
小结:一个晚上刷了四道题真爽 !!!
[3] http://www.cnblogs.com/remlostime/archive/2012/10/27/2742667.html
[4]http://blog.csdn.net/ithomer/article/details/8783952