LeetCode 16. 3Sum Closest

思路和LeetCode 15. 3Sum很相似

1. 排序数组num

2. 双层迭代,每一层都是和上一次迭代的数字相等时continue

3. 在[j+1, num.size()-1]中二分查找里target-num[i]-num[j]最近的数,复杂度为O(n^2 logn)。这里的trick是:

num = {1, 4, 7, 10, 13, 17, 20}, l = 2, r = 6, target = 14;

这时mid = (2+6)/2= 4, num[mid] = 13 < 14 = target. 若按照经典的二分策略,则l = mid + 1. 

但是,我们发现num[mid] < target < num[mid+1]. 我们考察num[mid]和num[mid+1], 发现比它小的num[mid]更接近target, 因此我们就break掉了迭代。直接返回num[mid]. 如下图的情况2所示:


具体实现可参考binary_search()函数里的while迭代:

class Solution 
{
public:
    int threeSumClosest(vector<int> &num, int target) 
    {
    	int closest = INT_MAX, ret;

    	sort(num.begin(), num.end());
    	for (int i = 0; i < int(num.size())-2; ++ i)
    	{
			if (i!=0 && num[i]==num[i-1])
			{
				continue;
			}
    		for (int j = i+1; j < int(num.size())-1; ++ j)
    		{
    			if (j!=i+1 && num[j]==num[j-1])
    			{
    				continue;
    			}
    			int ans = binary_search(num, target-num[i]-num[j], j+1) ;
    			if (closest > abs(target-num[i]-num[j]-ans))
                {
                    closest = abs(target-num[i]-num[j]-ans);
                    ret = num[i] + num[j] + ans;
                }
    		}
    	}   

    	return ret; 
    }
private:
	int binary_search(vector<int>& num, int target, int l)
	{
		int r = num.size()-1, mid;
		while (l <= r)
		{
			mid = (l+r)/2;
			if (num[mid] < target)
			{
                if (abs(target-num[mid]) >= abs(target-num[mid+1]))
                {
    				l = mid + 1;
                } else
                {
                    break;
                }
			} else if (num[mid] > target)
			{
                if (abs(target-num[mid]) >= abs(target-num[mid-1]))
                {
    				r = mid - 1;
                } else
                {
                    break;
                }
			} else
			{
				break;
			}
		}
        return num[mid];
	}
};




你可能感兴趣的:(LeetCode,C++,closest,binary_search,3Sum)