LeetCode16:3Sum Closest

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的问题,这个问题对于排序好的数组很好求解,使用两个指针,一个指针初始指向数组的第一个元素,一个指针初始指向最后一个元素,然后当这两个指针的值比target小时左边指针右移,值比target大时右边的指针左移,值和target相同时表示找到了和为target的两个数可以直接返回了。这样在O(N)的时间内就可以找到和最接近target的值,但是前提是排序好的数组。

针对这道求数组中3个数的和最接近target的问题,可以这么分析:首先将数组排序;然后遍历数组中的每一个元素(假设这个指针为first),那么原来的问题可以理解成了在[fist+1,last]的区间内查找和为target-*first的两个数的问题了。这样就可以在O(N^2)的时间内求解了。

代码如下:

class Solution {
public:
    int threeSumClosest(vector<int>& nums, int target) {
        //首先进行排序
        sort(nums.begin(),nums.end());

        //需要三个指针,第一个指针指向一个值时,第二个指针和第三个指针进行变化,将三个数的和转化成两个数的和的问题
        vector<int>::iterator first=nums.begin();
        vector<int>::iterator second;
        vector<int>::iterator last;

        //开始用排序后的前3个数来初始化返回值
        int closeResult=*first+*(first+1)+*(first+2);

        //从头开始遍历排序后的数组,每次固定一个值,然后在剩下的数组中从两头开始遍历,找到符合要求的值
        for(;first<nums.end()-2;first++)
        {
            second=first+1;
            last=nums.end()-1;
            int result=target-*first;

            //下面即在[second,last]这个数组中寻找和最接近result的两个数
            while(second<last)
            {
                if(abs(*second+*last-result)<abs(closeResult-target))
                    closeResult=*first+*second+*last;

                if((*second+*last)<result)
                    second++;
                else if((*second+*last)>result)
                    last--;
                else
                    return target;
            }
        }

        return closeResult;

    }
};

runtime:16ms

你可能感兴趣的:(LeetCode)