leetcode(16): 3Sum Closest

题目

Given an array nums of n integers and an integer target, find three integers in nums such that the sum is closest to target. Return the sum of the three integers. You may assume that each input would have exactly one solution.

Example:

Given array nums = [-1, 2, 1, -4], and target = 1.

The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).

解法一

在这里插入图片描述
暴力穷举,时间复杂度维O(N^3)

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

		sort(nums.begin(), nums.end());
		int distance =abs( target - nums[0] - nums[1] - nums[2]);
		int result = nums[0] + nums[1] + nums[2];
		for(int i = 0; i < nums.size() - 2; i++)
			for(int j = i+1; j < nums.size() - 1; j++)
				for (int k = j + 1; k < nums.size() ; k++){
					if (distance > abs(target - nums[i] - nums[j] - nums[k])) {
						distance = abs(target - nums[i] - nums[j] - nums[k]);
						result = nums[i] + nums[j] + nums[k];
					}		
				
				}	
		return result;
			}

};

解法二

在这里插入图片描述
基于方法一的优化
通过分析,我们可以想到一种时间复杂度为O(n^2)的解法:假设数组中有len个元素,首先我们将数组中的元素按照从小到大的顺序进行排序。其次,看最终取出的三个数中的第一个数,若数组长度为n,那么有n种取法。假设取的第一个数是A[i],那么第二三两个数从A[i+1]~A[len]中取出。找到“第一个数为A[i]固定,后两个数在A[i]后面元素中取。并且三数之和离target最近的情况。”这时,我们用两个指针j,k分别指向A[i+1]和A[len],如果此时三数之和A[i]+A[j]+A[k]<target,说明三数之和小了,我们将j后移一格;反之,若和大于target,则将k前移一格;直到j和k相遇为止。在这期间,保留与target最近的三数之和。一旦发现有“和等于target的情况”,立即输出即可。

由于取的第一个数可以是A[0],A[1],A[2],……,A[len-1],所以需要重复以上步骤n次。

为什么第一个数取了A[i]之后,第二三两个数只能在A[i+1]~A[len]中取呢? 因为这样可以避免重复。假设第二个数取了A[i-2],那么这样情况势必会包含在第一个数取A[i-2]的情况中。因为取出的三个数之间是没有顺序关系的。


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

		sort(nums.begin(), nums.end());
		int distance = abs(target - nums[0] - nums[1] - nums[2]);
		int result = nums[0] + nums[1] + nums[2];
		int nowResult = nums[0] + nums[1] + nums[2];
		for (int i = 0; i < nums.size() - 2; i++) {
			int j = i + 1;
			int k = nums.size() - 1;
			nowResult = nums[i] + nums[j] + nums[k];
			while (j < k) {
				if (nowResult < target)
					j++;
				else
					k--;
				if (distance > abs(target - nowResult)) {

					result = nowResult;
					distance = abs(target - nowResult);

				}
				nowResult = nums[i] + nums[j] + nums[k];
			}
		}


		return result;
	}

};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值