【LeetCode】15. 3Sum

题目:

Given an array nums of n integers, are there elements abc in nums 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.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

描述:

题目个给出一个数组,若某三数字的和为0,则输出这三个数字。

 

分析:

没有数据范围的题目真心不想做

 

最简单直接的方法是三层循环遍历求出所有满足情况的解,然后利用set进行去重,时间复杂度O(n^3),空间复杂度为O(1),见代码一,

然而会超时...

 

首先探索本问题的简化版:

从一个有序数组(从左到右单调不减)中查找和为指定值的两个数

可以使用两个指针,一个指向最大项,一个指向最小项,若两个指针所指元素和大于目标值,即说明需要缩小两数和,则较大元素指针左移,若两元素和小于目标值,即说明需要增大两数和,较小元素的指针右移,若相等,则记录是两个元素。

 

本题目可以分解为两步:

1,固定一个数x

2,在剩余的数中查找和为-x的两个元素(刚好是上述简化版问题)

 

(然后思维还是没有打开,只想到了问题的简化版,却没继续往下想,太局限了...)

 

借鉴了网上的双循环做法,差点吐血了,思路完全一致,但是运行结果一直有问题...

感觉可以用lower_bound函数和upper_bound函数去跳过相同的数字,结果一直RE是什么鬼东西...

 

--------------------------------------

2019.04.02  8:40

又尝试了一遍,确实可以用lower_bound函数和upper_bound函数,不过感觉简化的不多(代码三)

 

代码一:(时间复杂度O(n^3))

class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        set<vector<int>> result_set;
        
        for (int i = 0; i < nums.size(); ++ i) {
        	for (int j = i + 1; j < nums.size(); ++ j) {
        		for (int k = j + 1; k < nums.size(); ++ k) {
        			if (nums[i] + nums[j] + nums[k] == 0) {
        				vector<int> temp;
        				temp.push_back(nums[i]);
        				temp.push_back(nums[j]);
        				temp.push_back(nums[k]);
        				sort(temp.begin(), temp.end());
        				result_set.insert(temp);
					}
				}
			}
		}
		vector<vector<int>> result;
		for (auto it = result_set.begin(); it != result_set.end(); ++ it) {
			result.push_back(*it);
		}
        return result;
    }
};

 

代码二:(时间复杂度O(n^2))


class Solution {
public:
    vector< vector<int> > threeSum(vector<int>& nums) {
    	int len = nums.size();
    	//先排序 
    	sort(nums.begin(), nums.end());
    	
        vector< vector<int> > result;
        for(int i = 0; i < len; ++ i) {
        	int target = - nums[i], j = i + 1, k = len - 1;
			while (j < k) {
				int current = nums[j] + nums[k];
				if (current < target) {
					++ j;
				} else if (current > target) {
					-- k;
				} else {
					vector<int> temp;
					temp.push_back(nums[i]);
					temp.push_back(nums[j]);
					temp.push_back(nums[k]);
					result.push_back(temp);
					
					int left = nums[j], right = nums[k];
					while(j < k && nums[j] == left) {
						++ j;
					}
                    while(j < k && nums[k] == right) {
                    	-- k;
					}
				}
			}
			while(i + 1 < len && nums[i + 1] == nums[i]) {
				++ i;
			}
		}
        return result;
    }
};

代码三:(跟代码二基本完全一样)

class Solution {
public:
    vector< vector<int> > threeSum(vector<int>& nums) {
    	int len = nums.size(), i = 0;
    	//先排序 
    	sort(nums.begin(), nums.end());
    	
        vector< vector<int> > result;
        while (i < len) {
        	int target = - nums[i], j = i + 1, k = len - 1;
			while (j < k) {
				int current = nums[j] + nums[k];
				if (current < target) {
					++ j;
				} else if (current > target) {
					-- k;
				} else {
					vector<int> temp;
					temp.push_back(nums[i]);
					temp.push_back(nums[j]);
					temp.push_back(nums[k]);
					result.push_back(temp);
					
					int left = nums[j], right = nums[k];
					while(j < k && nums[j] == left) {
						++ j;
					}
                    while(j < k && nums[k] == right) {
                    	-- k;
					}
				}
			}
			int count = upper_bound(nums.begin(), nums.end(), nums[i]) - 
			lower_bound(nums.begin(), nums.end(), nums[i]);
			i += count;
		}
        return result;
    }
};

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值