4Sum

4Sum

Given an array S of n integers, are there elements abc, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.

Note:

  • Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
  • The solution set must not contain duplicate quadruplets.

    For example, given array S = {1 0 -1 0 -2 2}, and target = 0.

    A solution set is:
    (-1,  0, 0, 1)
    (-2, -1, 1, 2)
    (-2,  0, 0, 2)
思路和3Sum问题基本相同。
/** 整理的提交代码
 * 处理复杂度为O(n4),其中的去重效率也不是很高
 * 主要思路:(穷举所有,最后使用标准程序库中的算法进行去重)
 * 1、为了选出的四元组是非递减的,先对输入数组进行排序
 * 2、穷举法选取符合条件的四元组,由于每个元素只能取一次,所以当前循环的起始为上次循环起始之后
 * 3、由于原始输入数组本身可能包含重复元素,所以需要对选取到的四元组进行筛选移除重复四元组
 * 提交结果: 
 * (Judge Small) 
 * Run Status: Accepted! 
 * Program Runtime: 4 milli secs (基本在几毫秒) 
 * Progress: 15/15 test cases passed. 
 * (Judge Large) 
 * Run Status: Time Limit Exceeded (超时)
 */
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;

class Solution {
public:
	vector<vector<int> > fourSum(vector<int> &num, int target) {
		// Start typing your C/C++ solution below
		// DO NOT write int main() function
		sort(num.begin(), num.end());
		size_t size = num.size();

		vector<int> quadruplet;
		vector<vector<int> > result;

		 for (size_t i = 0; i < size; i++)
        {
            for (size_t j = i+1; j < size; j++)
            {
                for (size_t k = j+1; k < size; k++)
                {
					for (size_t t = k+1; t < size; t++)
					{
						if (num[i] + num[j] + num[k] + num[t] == target)
						{
							quadruplet.push_back(num[i]);
							quadruplet.push_back(num[j]);
							quadruplet.push_back(num[k]);
							quadruplet.push_back(num[t]);
							result.push_back(quadruplet);
							quadruplet.clear();
						}
					}
                }
            }
        }
        
        vector<vector<int> >::iterator end = result.end();
		sort(result.begin(), result.end(), less<<vector<int> >());	// 此处必须排序,排序元素为四元祖
        vector<vector<int> >::iterator new_end = unique(result.begin(), end);
        result.erase(new_end, end);

		return result;
	}
};

int main()
{
	int target;
	cout << "input target: ";
	cin >> target;

	vector<int> num;
	int number;
	cout << "input an integer array: ";
	while (cin >> number)
	{
		num.push_back(number);
	}

	vector<vector<int> > result;

	Solution s;
	result = s.fourSum(num, target);

	for (size_t i = 0; i < result.size(); i++)
	{
		for (size_t j = 0; j < 4; j++)
		{
			cout << result[i][j] << ' ';
		}
		cout << endl;
	}

	return 0;
}

/** 整理的提交代码
 * 处理复杂度为O(n3),其中的去重效率有所很高,“实时”去重
 * 主要思路:(穷举第一个和第二个元素,对第三个和第四个元素使用首尾逼近来枚举)
 *	 具体思路和求3Sum的O(n2)方法相同
 * 提交结果: 
 * (Judge Small) 
 * Run Status: Accepted! 
 * Program Runtime: 4 milli secs (基本在几毫秒) 
 * Progress: 15/15 test cases passed. 
 * (Judge Large) 
 * Run Status: Accepted!
 * Program Runtime: 1420 milli secs	(基本稳定在一点四毫秒左右) 
 * Progress: 282/282 test cases passed.
 */
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class Solution {
public:
	vector<vector<int> > fourSum(vector<int> &num, int target) {
		// Start typing your C/C++ solution below
		// DO NOT write int main() function
		vector<int> quadruplet;
		vector<vector<int> > result;

		sort(num.begin(), num.end());
		size_t size = num.size();
		if (size < 4)
		{
			return result;
		}

		int sum = 0;
		// 下标ijkt为四元组各元素的下标
		size_t i = 0, j = i+1, k = j+1, t = size-1;
		for (i = 0; i < size-3; i++)
        {
			if (i > 0 && num[i] == num[i-1])
			{
				continue;
			}
            for (j = i+1; j < size-2; j++)
            {
				if (j > i+1 && num[j] == num[j-1])
				{
					continue;
				}

				k = j + 1;
				t = size - 1;
				while (k < t)
				{
					if (k > j+1 && num[k] == num[k-1])
					{
						k = k + 1;
						continue;
					}
					sum = num[i] + num[j] + num[k] + num[t];
					if (sum == target)
					{
						quadruplet.push_back(num[i]);
						quadruplet.push_back(num[j]);
						quadruplet.push_back(num[k]);
						quadruplet.push_back(num[t]);
						result.push_back(quadruplet);
						quadruplet.clear();
						k = k + 1;
						if (num[k] == num[k-1])
						{
							k = k + 1;
						}
					}
					else if (sum < target)
					{
						k = k + 1;
						if (num[k] == num[k-1])
						{
							k = k + 1;
						}
					}
					else
					{
						t = t -1;
						if (num[t] == num[t+1])
						{
							t = t - 1;
						}
					}
				}
            }
        }

		return result;
	}
};

/** 整理的提交代码
 * 处理复杂度为O(n3),其中的去重效率有所很高,使用数据结构记录符合条件的元祖,查找去重
 * 主要思路:(穷举第一个和第二个元素,对第三个和第四个元素使用首尾逼近来枚举)
 *	 具体思路和求3Sum的O(n2)方法相同,只是去重方法不同
 *   为了避免直接查找string,对符合条件的元组进行了哈希,将这个元组的哈希函数返回值放入某个数据结构来标记该
 *   符合条件的元组已经找出了,下次哈希到相同的结果认为它们原来的元组相同(假设哈希未出现冲突),则跳过保存该结果。
 *   为了在求得符合条件的四元组后查找其哈希值时,提高查找速度,使用set或map来存储哈希值,其中的哈希值有序排列
 *   调用这两种容器自身的查找函数可以提高查找效率(内部一般使用二分查找法)。
 *   这里使用map和set在提交结果的时间上有所差别,应该二者内部实现还是有些差别,虽然可以将set也看做一种特殊map。
 * 提交结果: 
 * (Judge Small) 
 * Run Status: Accepted! 
 * Program Runtime: 8 milli secs (基本在几毫秒)(使用map去重约为0毫秒)
 * Progress: 15/15 test cases passed. 
 * (Judge Large) 
 * Run Status: Accepted!
 * Program Runtime: 948 milli secs	(基本稳定在九百多毫秒) (使用map去重约为600多毫秒)
 * Progress: 282/282 test cases passed.
 */
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
using namespace std;

class Solution {
public:
	long RSHash(string str)  
	{  
		int a = 876283;  
		int b = 21382;  
		long hash = 0;  
		for(size_t i = 0; i < str.size(); i++)  
		{  
			hash = a * hash + str[i];  
			a = a * b;  
		}  
		return hash;  
	}  
	vector<vector<int> > fourSum(vector<int> &num, int target) {
		// Start typing your C/C++ solution below
		// DO NOT write int main() function
		vector<int> quadruplet;
		vector<vector<int> > result;

		sort(num.begin(), num.end());
		size_t size = num.size();
		if (size < 4)
		{
			return result;
		}

		string str;
		set<long> lSet;
		long hash;
		int sum = 0;
		// 下标ijkt为四元组各元素的下标
		size_t i = 0, j = i+1, k = j+1, t = size-1;
		for (i = 0; i < size-3; i++)
        {
			/*if (i > 0 && num[i] == num[i-1])
			{
				continue;
			}*/
            for (j = i+1; j < size-2; j++)
            {
				/*if (j > i+1 && num[j] == num[j-1])
				{
					continue;
				}*/

				k = j + 1;
				t = size - 1;
				while (k < t)
				{
					/*if (k > j+1 && num[k] == num[k-1])
					{
						k = k + 1;
						continue;
					}*/
					sum = num[i] + num[j] + num[k] + num[t];
					if (sum == target)
					{
						str.clear();
						str += num[i];
						str += num[j];
						str += num[k];
						str += num[t];
						hash = RSHash(str);
						if (lSet.find(hash) == lSet.end())
						{
							lSet.insert(hash);
							quadruplet.push_back(num[i]);
							quadruplet.push_back(num[j]);
							quadruplet.push_back(num[k]);
							quadruplet.push_back(num[t]);
							result.push_back(quadruplet);
							quadruplet.clear();
						}
						k = k + 1;
						/*if (num[k] == num[k-1])
						{
							k = k + 1;
						}*/
					}
					else if (sum < target)
					{
						k = k + 1;
						/*if (num[k] == num[k-1])
						{
							k = k + 1;
						}*/
					}
					else
					{
						t = t -1;
						/*if (num[t] == num[t+1])
						{
							t = t - 1;
						}*/
					}
				}
            }
        }

		return result;
	}
};

参考:几种字符串哈希函数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值