leetcode 16. 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).


class Solution {
	struct Info
	{
		vector<pair<int, int>>pre;//pair<int,int>里的first代表sinnums里的index,second代表个数  
		int remainsize;//剩余的数字个数  
		int remainvalue;//剩余的值  
	};
	bool choose_one(int&k, vector<Info>&candi, map<int, int>&count, vector<int>sinnums)
	{
		vector<Info>newcandi;
		if (k == 1)
		{
			k--;
			for (int i = 0; i < candi.size(); i++)//考虑0  
				if (candi[i].remainvalue%candi[i].remainsize == 0)
				{
					int nxtnum = candi[i].remainvalue / candi[i].remainsize;
					if (nxtnum>sinnums[candi[i].pre.back().first] && count.find(nxtnum) != count.end()
						&& count[nxtnum] >= candi[i].remainsize)
						return true;
				}
		}
		else
		{
			for (int i = 0; i < candi.size(); i++)
			{
				for (int j = 1; j <= (candi[i].remainsize - k + 1); j++)
				{
					for (int h = candi[i].pre.back().first + 1; (h < sinnums.size() - k + 1); h++)
					{
						//粗略做判断,减小候选集大小  
						if (candi[i].remainvalue <= sinnums[h] * j + sinnums.back()* (candi[i].remainsize - j) 
							&& candi[i].remainvalue >= sinnums[h] * j + sinnums[h + 1] * (candi[i].remainsize - j) 
							&& j <= count[sinnums[h]])
						{
							Info info;
							info.pre = candi[i].pre;
							info.pre.push_back(pair<int, int>(h, j));
							info.remainsize = candi[i].remainsize - j;
							info.remainvalue = candi[i].remainvalue - j*sinnums[h];
							newcandi.push_back(info);
						}
					}
				}
			}
			k--;
			candi = newcandi;
		}
		return false;
	}
	bool threeSum(vector<int>& nums, int target)
	{
		if (nums.empty())
			return false;
		map<int, int>count;
		for (int i = 0; i < nums.size(); i++)
			count[nums[i]]++;
		map<int, int>::iterator it = count.end(); it--;
		if (target >= 0 && count.begin()->first> target
			|| target < 0 && it->first < target)
			return false;
		vector<int>sinnums;
		for (it = count.begin(); it != count.end(); it++)
			sinnums.push_back(it->first);
		int neednum = 3;
		//答案里只有一种数字  
		if (target%neednum == 0 && count.find(target / neednum) != count.end() && count[target / neednum] >= neednum)
			return true;
		for (int i = 0; i < sinnums.size(); i++)
		{
			//答案里有k种数字,2<=k<=neednum  
			for (int k = 2; k <= neednum; k++)
			{
				if (sinnums.size() - i >= k)
				{
					int jjmax = neednum - k + 1 < count[sinnums[i]] ? neednum - k + 1 : count[sinnums[i]];
					for (int j = 1; j <= jjmax; j++)
					{
						Info inf;
						inf.pre.push_back(pair<int, int>(i, j));
						inf.remainsize = neednum - j;
						inf.remainvalue = target - j*sinnums[i];
						vector<Info>candi;
						candi.push_back(inf);
						int kk = k - 1;
						bool f = false;
						while (kk > 0 && !f)
							f = choose_one(kk, candi, count, sinnums);
						if (f)
							return true;
					}
				}
			}
		}
		return false;
	}
public:
	int threeSumClosest(vector<int>& nums, int target)
	{
		int pp = 0;
		bool f = threeSum(nums, target);
		if (f)
			return target;
		while (true)
		{
			f = threeSum(nums, target + pp);
			if (f)
				return target + pp;
			f = threeSum(nums, target - pp);
			if (f)
				return target - pp;
			pp++;
		}
	};
};

acceped

还是借上题的代码。。。

你可以说我是刷博客吧




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值