三数之和[LeetCode-15]

188 阅读1分钟

题目描述

思路分析

  • 三数之和,可以转化为两数之和的问题,依次遍历原数组,比如当前遍历到index为5的元素,只要另外两个值相加为0减nums[5]即可。而这两个值对应的下标假设分别为left和right,right即为nums.size()-1,left不需要从0开始,因为在遍历5之前,先遍历的0-4,因此如果在0-4有符合条件的,在遍历0-4时,5已经作为一个结果放进结果数组里了,因为不需要有重复的结果,所以left从index+1开始。
  • 另外,如果相邻的2个值是一样的,则忽略,因为如果相等,意味着如果结果包含这两个值,则结果只需要保留先遍历到的即可,比如原数组为[-1, -1, 0, 1, 2],结果为[-1, -1, 2],很明显遍历index 0时,因为结果包含连续的两个-1,则遍历index 1时,只需要判断与前一个相等,即可继续前进,忽略当前值。

代码实现

class Solution
{
public:
	vector<vector<int>> threeSum(vector<int>& nums)
	{
		// 先排序
		sort(nums.begin(), nums.end());

		vector<vector<int>> res;
		for (int i = 0; i < nums.size(); i++) {
		    // 判断原因见上面解释的第二条
			if (i != 0 && nums[i] == nums[i - 1])
				continue;

			int dst = -1 * nums[i];
			
			// nums[i]为基准值,因此left从i+1开始
			int left = i + 1, right = nums.size() - 1;
			while (left < right) {
				int sum = nums[left] + nums[right];
				if (sum == dst) {
					res.push_back(vector<int>{nums[i], nums[left], nums[right]});
					left++;

					while (left < right && nums[left] == nums[left - 1]) {
						left++;
					}
						
					right--;
					while (left < right && nums[right] == nums[right + 1]) {
						right--;
					}
				} else if (sum > dst) {
					right--;
				} else {
					left++;
				}
			}
		}
		return res;
	}
};