LeetCode算法 —— 四数之和(排序 / 双指针原理)

原理和 三数之和是一样的,只不过加了一个数,我们只需要把第二个数限制在一个区域内活动就行了

题目:
给定一个包含 n 个整数的数组 nums 和一个目标值 target,判断 nums 中是否存在四个元素 a,b,c 和 d ,使得 a + b + c + d 的值与 target 相等?找出所有满足条件且不重复的四元组。

注意:
答案中不可以包含重复的四元组。

示例:
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0。

满足要求的四元组集合为:
[
[-1, 0, 0, 1],
[-2, -1, 1, 2],
[-2, 0, 0, 2]
]

最外层循环遍历第一个数n,第二个数在[n+1,总的长度 - 3] 中活动,第三个数 == 第二个数 + 1 . . . 其它是和 三数之和原理是一样的 . . .


代码如下所示:


class Solution {
public:
	vector<vector<int>> fourSum(vector<int>& nums, int target) {
		vector<vector<int>> retArr;

		if (nums.size() < 4)
			return retArr;
		else if (nums.size() == 4) {
			if (nums[0] + nums[1] + nums[2] + nums[3] == target)
				retArr.push_back({ nums[0],nums[1],nums[2],nums[3] });
			return retArr;
		}

		sort(nums.begin(), nums.end());		// 排序,很重要的一步

		for (size_t i = 0; i < nums.size() - 3; i++)		// 限制范围
		{
			if (i > 0 && nums[i] == nums[i - 1]) continue;

			// i + 1 表示第二个数
			auto result = threeSum(nums, i + 1, i + 2, nums.size() - 1, target, nums[i]);

			retArr.insert(retArr.end(), result.begin(), result.end());
		}

		return retArr;
	}

private:
	vector<vector<int>> threeSum(vector<int> nums, int index, int start, int end, int target, int value) {
		vector<vector<int>> answer;

		for (size_t i = index; i < nums.size() - 2; i++)	// 第二个数的活动范围
		{
			start = i + 1;				// 初始在第二数的后面
			end = nums.size() - 1;

			while (start < end) {
				int sum = nums[start] + nums[end] + nums[i] + value;

				if (sum < target) {
					++start;
				}
				else if (sum > target) {
					--end;
				}
				else {
					answer.push_back({ value,nums[i],nums[start] , nums[end] });

					while (start < end && nums[start] == nums[start + 1]) {
						++start;
					}
					++start;

					while (start < end && nums[end] == nums[end - 1]) {
						--end;
					}
					--end;
				}
			}

			// 判断第二个数有没有被计算过
			while (i < nums.size() - 1 && nums[i] == nums[i + 1]) {
				++i;
			}
		}

		return answer;
	}
};

猜你喜欢

转载自blog.csdn.net/weixin_42100963/article/details/107419473
今日推荐