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

Leetcode刷题38-16.最接近的三数之和(C++)

2019-03-28 16:34 531 查看

题目来源:链接: [https://leetcode-cn.com/problems/3sum-closest/].

16.最接近的三数之和

1.问题描述

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。
示例:

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.
与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).

2.我的解决方案

方法1. 首先想到的当然时暴力解决法(但是超时,3个for循环搞定)时间复杂度为大O的3次方:
暴力法思路如下:

  1. 将 所有可能的 三个数相加 的 和 统计出来,存入容器中。
  2. 分别与target 相减(负数取绝对值),存入另一个容器中
  3. 然后从小到大排序,第一个就是要求的值。
    暴力法代码如下:
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target)  {
int l = nums.size();
int best = nums[0]+nums[1]+nums[2];
for(int i=0;i<l-2;i++)
{
for(int j=i+1;j<l-1;j++)
{
for(int k=j+1;k<l;k++)
{
int t = nums[i]+nums[j]+nums[k];
if(abs(t-target)<abs(best-target))
{
best = t;
}
}
}
}
return best;
}
};

方法2. 大体思路和昨天的 11.盛最多水的容器(C++)差不多 链接—>添加链接描述

  1. 首先将nums从小到大排序
  2. 先固定住一个(即 i 先固定住),然后定义两个辅助指针left 和 right 变量遍历。
  3. 由于nums是排序的,因此如果 三数之和 threeSum 大于 target,说明 right对应的值大了,需要 减减right(–right),反之则 ++left。若等于targer,说明很完美,直接return target。

时间复杂度为大O方

代码如下:

class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {

int len = nums.size();
sort(nums.begin(), nums.end());
int closeSum = nums[0] + nums[1] + nums[2];
for(int i = 0; i < len - 2; ++i)
{
int left = i + 1;
int right = len - 1;
while(left < right)
{
int threeSum = nums[i] + nums[left] + nums[right];
if(abs(threeSum - target) < abs(closeSum - target))
{
closeSum = threeSum;
}
if(threeSum < target)
{
++left;
}
else if(threeSum > target)
{
--right;
}
else
{
return target;
}
}
}
return closeSum;
}
};

3.大神们的解决方案

思路大同小异,都是用 两个辅助指针变量 节省时间。

static const auto __ = []() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
return nullptr;
}();
//以上加速专用。。。

class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
sort(nums.begin(), nums.end());
int re = INT_MAX, len = nums.size();
int left = 0, right = len - 1;
int num1, num2, num3, now, min_abs = INT_MAX;
for(auto i = 0; i < len; ++i)
{
num1 = nums[i];
for(left = i + 1, right = len - 1; left < right;)
{
now = num1 + nums[left] + nums[right];
if(target == now)
return now;
if(abs(target - now) < min_abs)
{
re = now;
min_abs = abs(target - now);
}
if(now > target)
right--;
else
left++;
}
}
return re;
}
};

4.我的收获

暴力解决法虽然好但是。。。超时啊

2019/3/28 胡云层 于南京 38

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