LeetCode——15.3Sum

首次使用LeetCode学习算法设计,希望通过本次学习可以提高自己对各种算法的了解。


本次选择的题目是15.3Sum,属于medium难度。该题目的描述是“Given an array S of n integers, are there elements abc in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.Note: The solution set must not contain duplicate triplets.”也就是说,给定一个有n个整数的数组S,在S中,是否能找到a,b和c三个数,使得a+b+c=0成立?找出所有唯一的三元组。注意的是,结果集不能包含重复的三元组。举个例子:


给定数组 S = [-1, 0, 1, 2, -1, -4]
结果集是:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

本题目的思路与Two Sum类似,将-a作为目标值,在数组S中找到两个数相加正好等于-a即可。按照这种想法,通过三层循环可以找到结果的元组,为了避免重复,首先对数组S进行排序,接着循环,然后使用unique函数使得vector中的元素唯一。然而,这种暴力的做法会导致超时。因此,需要其他的方法来替代unique函数。

在对数组S进行排序后,相同的整数排在一起。因此,我的思路是在最外层的每次循环(假设循环量是k)后,都要判断S[k+1]是否和S[k]一样,可以防止出现重复。如上面例子数组排序后是S = [-4, -1, -1, 0, 1, 2],当S[k] = -1,即a=-1时,找到b和c相加等于1,即0和1;在选择S[k+1]前,发现S[k+1]和S[k]相同,必然会出现同样一个三元组,因此直接跳过S[k+1]即可避免重复。同理,对于找到数b和数c的循环,也需要进行同样的判断。代码如下。

	for(int k = 0; k < nums.size(); k ++){
 		int target = 0 - nums[k];
 		int rest = 0;
 		i = k+1;
 		for (; i < nums.size();i ++)
 		{
 			rest = target - nums[i];
 			for (j = i+1; j < nums.size(); j ++)
 			{
 				if (rest == nums[j])
 				{
 					vector<int> vec;
 					vec.push_back(nums[k]);
 					vec.push_back(nums[i]);
 					vec.push_back(nums[j]);
 					res.push_back(vec);
 				}
 				while ((j + 1 < nums.size()) && (nums[j] == nums[j+1]))
 			 				j ++;
 			}
			while ((i + 1 < nums.size()) && (nums[i] == nums[i+1]))
 			 				i ++;
 		}
 		while ((k + 1 < nums.size()) && (nums[k] == nums[k+1]))
 				k ++;
 	}

然而,这种做法没有使用unique函数,但是循环多了,还是会超时。所以根据提示使用两个指针的话,那么考虑数b和数c的查找分别从前和后两个位置开始找。b首先取得是S[k+1]的值,c首先取的是S[S.size()-1]的值,按照b+c的大小,移动两个循环变量i和j。若发现相等,则记录到vector中,同时,处理b和c可能重复的部分。代码如下所示。结果不会超时。

vector<vector<int> > threeSum(vector<int>& nums) {
 	vector<vector<int> > res;
 	sort(nums.begin(),nums.end());
 	
 	for(int k = 0; k < nums.size(); k ++){
 		int target = 0 - nums[k];
 		int i = k+1;
 		int j = nums.size() -1;

 		while (i < j)
 		{
 			if(nums[i] + nums[j] < target)
 				i ++;
 			else if(nums[i] + nums[j] > target)
 				j --;
 			else {
 	 			vector<int> vec;
 	 			vec.push_back(nums[k]);
 	 			vec.push_back(nums[i]);
 	 			vec.push_back(nums[j]);
 	 			res.push_back(vec);

 	 			while ((i < j) && (nums[i] == vec[1]))
 	 				i ++;
 	 			while ((i < j) && (nums[j] == vec[2]))
 	 				j --;
 	 		}
 		}
 		 while ((k + 1 < nums.size()) && (nums[k] == nums[k+1]))
 			k ++;
 	}
	return res;
}


点赞