【Leetcode】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)

代码

typedef struct node_s{
    int leftIndex;
    int rightIndex;
	int twoSum;
}node;


bool compileM(const int &a , const int &b)
{
	return a < b;
}

class Solution {
public:
    vector<vector<int> > fourSum(vector<int> &num, int target) {
        map<int, list<node>* >mymap;
		vector<vector<int> > resultV;
		
		if (num.size() < 4) {
			return resultV;
		}
		
		vector<int> temp(num);
		sort(temp.begin(), temp.end(), compileM);
		
		/* create a map O(N^2)*/
		for (int i = 0 ; i < temp.size(); i++) {
			for (int j = i+1 ; j < temp.size(); j++) {
				node myNode;
				myNode.leftIndex = i;
				myNode.rightIndex = j;
				myNode.twoSum = temp[i] + temp[j];
				list<node>* mylist = mymap[ temp[i] + temp[j]];
				if (!mylist) {
					mylist = new list<node>;
					mymap[ temp[i] + temp[j]] = mylist;
				}
				mylist->push_back(myNode);
			}
		}

		map<int, list<node>* >::iterator beginiter = mymap.begin();
		map<int, list<node>* >::iterator enditer = mymap.end();
		
		
	
#if 1
		
		for (; beginiter != enditer; beginiter++) {
			
			list<node>* rightList = mymap[target - beginiter->first];
			if (!beginiter->second) {
				continue;
			}
			
			if (rightList && rightList->size() > 0)
			{
				
				/* equal */
				list<node>* leftList = beginiter->second;
				for (list<node>::iterator leftListIter = leftList->begin() ; leftListIter !=leftList->end();leftListIter ++) {
					for (list<node>::iterator rightListIter = rightList->begin(); rightListIter != rightList->end(); rightListIter ++) {
						node node1 = *leftListIter;
						node node2 = *rightListIter;
						if (node1.leftIndex != node2.leftIndex && node1.leftIndex != node2.rightIndex &&
							node1.rightIndex != node2.leftIndex && node1.rightIndex != node2.rightIndex &&
							node1.leftIndex < node2.leftIndex) {
		
				
							
							int tempA[4];
							tempA[0] = temp[node1.leftIndex];
							tempA[1] = temp[node1.rightIndex];
							tempA[2] = temp[node2.leftIndex];
							tempA[3] = temp[node2.rightIndex];
							vector<int> tempv(tempA,tempA+4);
							sort(tempv.begin(), tempv.end(), compileM);
							int kk =0;
							for (kk = 0; kk < resultV.size(); kk++) {
								if(resultV[kk][0] == tempv[0] &&
								   resultV[kk][1] == tempv[1] &&
								   resultV[kk][2] == tempv[2] &&
								   resultV[kk][3] == tempv[3])
								{
									break;
								}
							}
							
							if (kk == resultV.size()) {
								resultV.push_back(tempv);
								//cout<<tempv[0] << ","<<tempv[1] <<"," <<tempv[2]<<","<<tempv[3]<<endl;
							}
							
						}
					}
				}
				
			}
		}
		
#endif
		return resultV;
    }
};


分析

这里利用了map,这里的map当然可以换成hash_map咯。这里解释一下实现的思想。

使用map存下来所有两两相加的结果,并存入到链表中。

遍历整个map,并寻找出 target-a 的值是否有这样的节点(链表不为空)。

存在,则遍历整个链表,因为刚开始保存了所有的i,j,这样四个数只要保证没有重复计算某个下表,则这个四位数是可以接受的。(注意一个细节,遍历的 node 的小下表必须 < 找到的node的最小下表,理由是必须向后找,否则想前找会找到重复的组合)

然后排序这四个数,推入到vector中,完事。

时间复杂度是 O(N^2) + O(N)  = O(N^2)。空间复杂度也是 O(N^2)。


分析2

利用3sum的解法,先把问题分解成 3sum, 然后 2sum。。。

最后的复杂度比 3sum 多一次遍历,则复杂度是 O(N^3) , 但是空间没有损耗。

总结

各有优劣,被问到 如何使用O(N^2) 来实现4sum,貌似可以被问到。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值