算法练习(7):3Sum

题目:

题意:题目意思是从给出的数组中找出三个和为0的元素,返回所有的组合。

分析与思路:对于这种题,没做过这类题的第一反应肯定是暴力求解,三次循环,超出所有的组合然后查重去掉重复的。但是这当然会超时毕竟复杂度达到了O(n3),因此必须另寻出路。为了避免一些重复的遍历,对于找和为定值的两个数时,我们有一种方便的方法:就是先把数组排序(从小到大),然后从数组两端向中间移动,和大于目标则右端指针减一,小于目标左端指针加一,这样可以避免双重循环导致过多重复的遍历,还省去了查重去重的功夫。现在是找出和为0的三个数,那么可以把这道题变一下,在给出数组中取一个数的相反数作为目标,然后找出剩下的数中和为目标的两个数,这样的三个数就是一个组合。再作个优化,我们把排序后的数组从左到右取目标,然后每一轮的初始最左指针就可以指向目标的指针加1,这样就不会导致重复的组合出现了。

代码:

class Solution {
public:
	vector<vector<int>> threeSum(vector<int>& nums) {
		vector<vector<int>> result;
		if (nums.size() == 0 || nums.size() < 3) {//不满足条件的情况
			return result;
		}
		sort(nums.begin(), nums.end());//对数组排序
		for (int it = 0; it < nums.size()-2;it++) {//取目标值
			if (it > 0 && nums[it] == nums[it - 1]) continue;//对于同目标值的元素可以跳过,因为重复了
			int target = -(nums[it]);//取相反数
			int l = it + 1, r = nums.size() - 1;//设置左右指针
			while (l < r) {
				if (nums[l] + nums[r] == target) {
					vector<int> re;
					re.push_back(nums[it]);
					re.push_back(nums[l]);
					re.push_back(nums[r]);
					result.push_back(re);//把满足要求的组合加到答案中
					while (nums[r] == nums[r - 1]) r--;//因为按照左指针不变的情况下,右值相同会得到相同组合
					while (nums[l] == nums[l + 1]) l++;
					r--;
					l++;//已得匹配组合,则两端都需要移到分别跟原来不同值的位置才行
				}
				else {
					if (nums[l] + nums[r] < target) {//小于目标则左指针加1
						l++;
					}
					else {
						r--;
					}
				}
			}
		}
		return result;
	}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值