leetcode--TWO SUM延伸(假设答案不唯一、假设输入有相同数字)

leetcode中的TWO SUM对结果进行了限制,You may assume that each input would have exactly one solution.

但是考虑实际情况,有可能在数列中,有多个组合的sum等于target。需要找到所有的情况。

1,  假设:在输入的数列中没有重复的数字,结果中数对不唯一

sort之后不跳出循环,接着寻找对应的数对。直到寻找完

vector<pair<int, int>> twoSum(vector<int>& nums, int target) {
        vector<pair<int, int>> result;
    	vector<pair<int, int> > ipair;
    	size_t k = nums.size();
    	for (size_t i = 0; i < k; ++i)
    	{
    		ipair.push_back(make_pair(nums[i], i));
    	}
    	sort(ipair.begin(), ipair.end());
    	vector<pair<int, int>>::iterator pfound=ipair.begin(), pback = --ipair.end();
    	while (pfound < pback)
    	{
    		if (pfound->first + pback->first > target)
    			--pback;
    		else if (pfound->first + pback->first < target)
    			++pfound;
    		else
    		{
    			result.push_back(make_pair((pfound->second < pback->second ? pfound->second : pback->second) + 1),
    			(pfound->second > pback->second ? pfound->second : pback->second) + 1));
    		}
    	}
    	return result;
    }
如果用unordered_map的话,代码如下:

vector<pair<int, int>> twoSum(vector<int> &numbers, int target) {
        vector<pair<int, int>> result; //保存结果 
    	int count = numbers.size();
    	int temp1;
	unordered_map<int, int> numMap;
	unordered_map<int, int>::const_iterator citer;
	for(int j = 0; j < count; ++j)
	{
		temp1 = target - numbers[j];
		citer = numMap.find(temp1);
		if(citer != numMap.cend())
		{
			result.push_back(make_pair(citer->second + 1, j+1));		
		}
		else
			numMap[numbers[j]] = j;
		}
    	return result;
    }

2, 输入的数字有重复的情况,结果不唯

这个时候考虑的问题有点多,加入有个vector<int>,其中有100个元素均为1,求sum为2的数对,那么可以发现,此时答案有(1,2),(1,3)···(1,100),(2,3),(2,4),(2,100)···

这个时候任何算法,都要O(N^2)才能找完数对。但是实际情况我们能不能找到运算更快的算法,寻找结果(输入数字一般化,有重复但不都是相同的)?

答案是肯定的

烟客旅人  ( 烟客旅人 sigmainfy — tech-wonderland.net)有对这个问题的分析点击打开链接

但是这个分析有一定的局限性,就如above,所有元素有相同,而sum即为 self+self 的情况无法处理。


下面给出我的解法:

vector<pair<int, int>> twoSum(vector<int>& nums, int target) {
	vector<pair<int, int>> result;
	vector<pair<int, int> > ipair;
	size_t k = nums.size();
	for (size_t i = 0; i < k; ++i)
	{
		ipair.push_back(make_pair(nums[i], i));
	}
	sort(ipair.begin(), ipair.end());
	vector<pair<int, int>>::iterator p1 = ipair.begin(), p2 = --ipair.end();
	vector<pair<int, int>>::iterator oldp1 = p1;
	while (p1 < p2)
	{
		if (p1->first + p2->first > target)
		{
			--p2;
		}
		else if (p1->first + p2->first < target)
		{
			++p1;
		}
		else
		{
			result.push_back(make_pair(min(p1->second, p2->second)+1, max(p1->second, p2->second)+1));
			oldp1 = p1;
			++p1;
			while (p1->first + p2->first == target && p1 < p2)
			{
				result.push_back(make_pair(min(p1->second, p2->second)+1, max(p1->second, p2->second)+1));
				++p1;
			}
			p1 = oldp1;
			--p2;
		}
	}
	return result;
}

举例子分析:

原始数据: vector<int>  ivec{ 8,8, 5, 5, 5, 2, 3,3, 6, 9, 4, 1, 0, 7, 7, 7};

排序之后:0 1 2 3 3 4 5 5 5 6 7 7 7 8 8 9  (每个数字有对应的原始位置信息)

 然后设置两个迭代器p1, p2分别指向 head 和 tail ,在 p1->first + p2->first 不相等的情况下,我们根据sum 和target 的对比,移动 p1 或 p2。

问题出现在相等的时候,如果相等那么我们假设有重复数字出现(如果不相等,重复数字不考虑,会step by step 跳过)

这时我们用oldp1来保存第一次相等的时候p1的位置,然后p1+1。然后进入相等循环测试看 p1 之后的数字和oldp1的数字是否相等,如果相等,把数对加入result,如果不等,那么说明重复数字结束,跳出循环。最后把p1回到oldp1位置,把后迭代器向前移一个(--p2),重新循环寻找数对之和等于target。

如此便可把所有合适的数对都找出来。

注意:位置都是从1开始的。1,2,3,····


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值