【leetcode刷题自记录】15. 三数之和

题干

给你一个包含n个整数的数组nums,判断nums是否存在三个元素a,b,c,使得a+b+c = 0 ?请你找出所有和为0且不重复的三元组。
注意:答案中不可以包含重复的三元组。

示例

示例1

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]

示例2

输入:nums = []
输出:[]

示例3

输入:nums = [0]
输出:[]

题解

(一) 排序+双指针

时间复杂度:O(n^2) 空间复杂度:O(1)

思路及解法

边界情况:如果数组长度为null或者小于3,返回 []。
第一步:对数组进行排序;
第二步:遍历排序后的数组

 1. 如果nums[i] > 0:因为已经排好序,所以后面不可能有三个数相加和等于0,直接返回结果
 2. 对于重复元素:跳过,避免出现重复解
 3. 令左指针 L =i+1,右指针R = n -1,当 L < R时,执行循环:
		当nums[i] +nums[L] +nums[R] ==0, 执行循环,判断左界与右界是否和下一位置重复,去除重复解,并同时将L,R移到下一位置,寻找新的解
		如果和大于0,说明nums[R]太大,R左移;
		如果和小于0,说明nums[L]太小,L右移。
代码实现
public List<List<Integer>> threeSum(int[] nums){
	List<List<Integer>> lists = new ArrayList<>();
	//定义一个结果集
	Arrays.sort(nums);
	//排序
	int len = nums.length;
	for(int i = 0; i < len; i++){
		if (nums[i] > 0) return lists;
		//nums[i]为这三个数中的最小的数,如果nums[i]都大于零了,后面的更加不可能满足
		if (i > 0 && nums[i] == nums[i-1]) continue;
		//去重,当起始的值与上一个相同,那得到的答案一定相同
		int curr = nums[i]; //第一个数的值
		int L = i+1, R = len-1; //定义两个指针
		while(L < R) {
			int tmp = curr + nums[L] + nums[R];   
			//这三个数相加的值放到temp中
			if(tmp == 0){ //得到满足条件的解
				List<Integer> list = new ArrayList<>();
				list.add(curr);
				list.add(nums[L]);
				list.add(nums[R]);
				lists.add(list);  //将此次结果放入结果集中
				while(L < R && nums[L+1] == nums[L]) L++;  //去重,当第二个数出现重复
				while(L < R && nums[R-1] == nums[R]) R--;  //去重,当第三个书出现重复
				L++;
				R--;
				}else if (tmp < 0 ){  //和小于零,说明第二个数太小
					L++;
				}else {   //和大于零,说明第三个书太大
					R--;  
				}
			}
		}
		return lists;
	}

归纳与总结
  1. Arrays.sort()方法
    这种形式是对一个数组的所有元素进行排序,并且是按从小到大的顺序。
  2. 去重
    if (i > 0 && nums[i] == nums[i-1])
    continue; //这个continue还蛮难想的
  3. 合理减少工程量:当nums[i] > 0,后面的元素都不用比较了。这个点做题的时候没想到
  4. 其实就是一个降维过程,从三维降到二维,固定一个值,用双指针,一个在头一个在尾,往中间靠拢,找答案
  5. ArrayList是一个可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制
    add()方法,可以将元素添加到ArrayList中
    get()方法,可以访问ArrayList中的元素
    set()方法,可以修改ArrayList中的元素(第一个为索引位置,第二个为要修改的值)
    remove()方法,可以删除ArrayList中的元素(括号里是索引)
    size()方法,可以计算ArrayList中的元素数量
  6. 要格外注意数组越界情况,给nums[i]去重的时候还要并上条件i>0;tmp的定义要放在while(L>R)循环中,不然可能报错
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值