(LeetCode 16) 3Sum Closest

来源:互联网 发布:php 客户端ip 编辑:程序博客网 时间:2024/05/14 01:02

Q:
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

For example, given array S = {-1 2 1 -4}, and target = 1.The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

哎,一定要看清题啊。题意大致是先给你一个整型数组,然后给你一数target,让你在整型数组中找出三个数,这三个数的和与给定数的差的绝对值最小。

solution:
我看成求三个离给定数最近的数的和呢,闹腾了老半天结果过不了。
这道题的思路是:

  • 先对给定的整型数组进行升序排序
  • 从头开始遍历该数组,假设当前遍历到第i个数,暂时固定i
  • 设置两个指针分别是i+1(j)一个指向数组尾(k),然后求这两个数组指针所指值与第i个数的和,判断这个和是不是当前target最近的。如果小于,那么j向后移动一位,否则k向前移动一位,直到j>=k
  • i向前移动一位,重复第3步,直到整型数组全部被遍历

排序的时间复杂度是O(nlog(n))遍历的时间复杂度是O(n2),所以整个算法复杂度是O(n2)
这道题是可以进行剪枝的
1.假设当前遍历到i,如果3nums[i]target>abs(currentMinstarget),那么可以直接返回了。因为i后面的数都比nums[i]大,所以后面任意两个数与num[i]的和比起3*num[i]也会离target越来越远。
2.如果num[i]+2num[j]target>abs(currentMinstarget)那么可以跳出循环,j后面的数当前循环不用再遍历。i向后移动一位开始新的循环。

不过这道题的测试结果,剪枝带来的效率提升不大,反而带来了额外的计算量,可能是测试数据与这种剪枝不敏感,所以我就先注释掉了。但是后面有些题这种剪枝很有效果。

class Solution {public:    int threeSumClosest(vector<int>& nums, int target) {        sort(nums.begin(),nums.end());        int mins =nums[0]+nums[1]+nums[2];        int closestVal = abs(mins-target);        int size = nums.size();        for(int i=0;i<size-1;i++){            if(nums[i]*3-target>closestVal)return mins;            int j = i+1;            int k = size-1;            while(j<k){                //if(nums[i]+nums[j]*2-target>closestVal)break;                int sums = nums[i]+nums[j]+nums[k];                if(sums==target)return sums;                int val=abs(sums-target);                if(val<closestVal){                  mins=sums;                  closestVal = val;                }                 if(sums<target)j++;                 else k--;            }        }        return mins;    }};

Reference Link:
http://blog.csdn.net/booirror/article/details/44209355

0 0