依旧是老问题,成功提交但是超时,这次我是利用回朔的方式,寻找所有的三个组合形式,然后计算所有差距的最小值。这是一种时间复杂度为O(n^3)的解法。
class Solution {
public:
void dfs(int start,vector<int>& temp,map<int,int>& result,int target,vector<int>& nums)
{
if(temp.size()==3)
{
int sum=temp[0]+temp[1]+temp[2];
result[abs(sum-target)]=sum;
}
else
{
for(int i=start;i<nums.size();i++)
{
temp.push_back(nums[i]);
dfs(i+1,temp,result,target,nums);
temp.pop_back();
}
}
return;
}
int threeSumClosest(vector<int>& nums, int target) {
if(nums.size()<3)
return 0;
map<int,int> result;
vector<int> temp;
dfs(0,temp,result,target,nums);
/*for(set<int>::iterator it=result.begin();it!=result.end();it++)
cout<<*it<<endl;*/
/*int result1=*result.lower_bound (target);
int result2=*result.upper_bound (target);
cout<<result1<<" "<<result2;*/
return (*result.begin()).second;
}
};
想了很久,也没有想出来具体的解法,于是看了discuss。发现这个思路和我之前的一个想法很像,我之前打算用一个windows窗,固定左右的位置,然后在中间搜索最合适的值。但是总会有很多反例,因为考虑问题的方式不全面。但是discuss这个方法就没有这些问题了,因为他是先固定一个点,然后搜索另外两个点。一个很简单的思路,从估计两个找一个到固定一个找两个之间的改进
同时另外两个点是从当前搜素点的后一个位置开始搜索的,避免了三个组合时重复组合的情况。
其实这个方式和之前回朔的方式很像,不过进一步减少了回朔计算加和的次数,使得O(n^3)的时间复杂度经一步减少到O(n^2)。
最终AC的代码如下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
if(nums.size()<3)
return 0;
if(nums.size()==3)
return (nums[0]+nums[1]+nums[2]);
int closeSum=nums[0]+nums[1]+nums[2];
int closeDistance=abs(target-closeSum);
sort(nums.begin(),nums.end());
for(int i=0;i<nums.size()-2;i++)//i,j,k
{
int j=i+1;
int k=nums.size()-1;
while(j<k)
{
int sum=nums[i]+nums[j]+nums[k];
if(closeDistance>abs(sum-target))
{
closeDistance=abs(sum-target);
closeSum=sum;
}
if(sum<target)
j++;
else if(sum>target)
k--;
else
return sum;
}
}
return closeSum;
}
};