LeetCode第18题思悟——四数之和(4sum)

LeetCode第18题思悟——四数之和(4sum)

知识点预告

  1. 数组排序预处理:无序变有序;
  2. 去重操作的位置选择:去掉冗余代码;
  3. 遍历前的预判断处理:快速筛选处理;

题目要求

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/4sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

示例

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/4sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

我的思路

此题和leetcode第15题leetcode第16题属于同类型的题目,所以处理手段和知识点也是大同小异;

核心手段就是先排序,然后双重循环,遍历第1、2个数,然后通过双指针遍历寻找第3,4个数,然后需要注意去重处理;

public List<List<Integer>> fourSum(int[] nums, int target){
	List<List<Integer>> result=new ArrayList<>();
	if(nums.length<4){
		return result;
	}
	Arrays.sort(nums);
	int firstBorder=nums.length-3;
	int secondBorder=nums.length-2;
	int firstNum;
	int secondNum;
	int currentSum;
	int leftPointer,rightPointer,thirdNum,fourthNum;
	List<Integer> answer;
	for(int i=0;i<firstBorder;i++){
		firstNum=nums[i];
		for(int j=i+1;j<secondBorder;j++){
			secondNum=nums[j];
			leftPointer=j+1;
			rightPointer=nums.length-1;
			while(leftPointer<rightPointer){
				thirdNum=nums[leftPointer];
				fourthNum=nums[rightPointer];
				currentSum=firstNum+secondNum+thirdNum+fourthNum;
				if(currentSum<target){
					leftPointer++;
					while(leftPointer<rightPointer&&nums[leftPointer]==thirdNum){
						leftPointer++;
					}
				}else if(currentSum>target){
					rightPointer--;
					while(leftPointer<rightPointer&&nums[rightPointer]==fourthNum){
						rightPointer--;
					}
				}else{
					answer=new ArrayList<>();
					answer.add(firstNum);
					answer.add(secondNum);
					answer.add(thirdNum);
					answer.add(fourthNum);
					result.add(answer);
					while(leftPointer<rightPointer&&nums[leftPointer]==thirdNum){
						leftPointer++;
					}
					while(leftPointer<rightPointer&&nums[rightPointer]==fourthNum){
						rightPointer--;
					}
				}
			}
			while(j<secondBorder&&nums[j]==secondNum){
				j++;
			}
			j--;
		}
		while(i<firstBorder&&nums[i]==firstNum){
			i++;
		}
		i--;
	}
	return result;
}

优秀解法

//解法A
public List<List<Integer>> fourSum(int[] nums, int target) {
	List<List<Integer>> res = new LinkedList<>();
	Arrays.sort(nums);
	int n = nums.length;
	for (int i = 0; i < n - 3; i++) {
		if (i > 0 && nums[i] == nums[i - 1]) continue;
		if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) break;
		if (nums[i] + nums[n - 1] + nums[n - 2] + nums[n - 3] < target) continue;
		for (int j = i + 1; j < n - 2; j++) {
			if (j - i > 1 && nums[j] == nums[j - 1]) continue;
			if (nums[i] + nums[j] + nums[j + 1] + nums[j + 2] > target) break;
			if (nums[i] + nums[j] + nums[n - 1] + nums[n - 2] < target) continue;
			int left = j + 1;
			int right = n - 1;
			while (left < right) {
				int tmp = nums[i] + nums[j] + nums[left] + nums[right];
				if (tmp == target) {
					List<Integer> tmpList = new LinkedList<>(Arrays.asList(nums[i], nums[j], nums[left], nums[right]));
					res.add(tmpList);
					while (left < right && nums[left] == nums[left + 1]) left += 1;
					while (left < right && nums[right] == nums[right - 1]) right -= 1;
					left += 1;
					right -= 1;
				} else if (tmp > target) right -= 1;
				else left += 1;
			}
		}
	}
	return res;
}

差异分析

从当前提交情况来看,该题主流解法有两种,一种是我的思路一节中提到的解法,另一种就是优秀解法啦;而后者比前者运行情况更好一点;

除了共有的排序、双指针遍历等技巧外有些解法还有以下几个亮点:

  1. 去重位置的选择:这一点同第15题、第16题的分析,自己的解法中对于去重的处理显得很冗余;
  2. 前置条件的判断:可以快速筛选掉一些值,提高处理效率;算是遍历前的预处理;

知识点小结

  1. 数组排序预处理;
  2. 去重操作的位置选择;
  3. 遍历前的预判断处理;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值