三数之和/最接近的三数之和(java实现)

三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

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

	满足要求的三元组集合为:
	[
		 [-1, 0, 1],
		 [-1, -1, 2]
	]
方法一:暴力解法
遍历选取任意三个元素相加是否为零,利用Set去重。
	public List<List<Integer>> threeSum(int[] nums) {
        Set<List<Integer>> Set = new HashSet<List<Integer>>();
      	Arrays.sort(nums);
      	for(int i=0;i<nums.length-2;i++) 
      		for(int j=i+1;j<nums.length-1;j++) 
      			for(int k=j+1;k<nums.length;k++) 
					if(nums[i]+nums[j]+nums[k]==0)Set.add(Arrays.asList(nums[i],nums[j],nums[k]);
      	return new ArrayList<List<Integer>>(Set);
    }
  • 时 间 复 杂 度 : O ( n 3 ) 时间复杂度:O(n^{3}) O(n3)
  • 空 间 复 杂 度 : O ( 1 ) 空间复杂度:O(1) O(1)
方法二:双指针解法

固定三个指针中最左(最小)数字的指针 i,双指针 j,k 分设在数组索引 (i+1, nums.length-1) 两端,通过双指针交替向中间移动,记录 nums[i] + nums[j] + nums[k] == 0 时的nums组合:

	public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> List = new ArrayList<List<Integer>>();
        if(nums.length < 3) return List;
        Arrays.sort(nums); // 进行排序
        for (int i = 0; i < nums.length ; i++) {
            if(nums[i] > 0) break; // nums[i]大于0,则三数之和大于0,所以结束跳出
            if(i > 0 && nums[i] == nums[i-1]) continue; // 去掉重复
            for(int j=i+1,k=nums.length-1;j < k;){
                int He = nums[i] + nums[j] + nums[k];
                if(He == 0){
                	List.add(Arrays.asList(nums[i],nums[j],nums[k]));
                    while (j<k && nums[j] == nums[j+1]) j++; // 去掉左重复
                    while (j<k && nums[k] == nums[k-1]) k--; // 去掉右重复
                    j++; k--;
                }
                else if (He < 0) j++;
                else if (He > 0) k--;
            }
        }
        return List;
    }
  • 时 间 复 杂 度 : O ( n 2 ) 时间复杂度:O(n^{2}) O(n2)
  • 空 间 复 杂 度 : O ( 1 ) 空间复杂度:O(1) O(1)

最接近的三数之和

给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

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

	满足要求的三元组集合为:
	与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2)
方法一:双指针解法

与三数之和类似。三数之和要求找到三个元素之和为0的所有不重复情况,这里找到三个元素之和最接近目标值的情况(唯一)。首先对原数组排序,然后维护一个绝对差值变量和对应的结果变量。遍历数组,使用双指针j和k,根据三数之和与目标值的大小关系来移动指针,注意跳过重复情况,并记录与目标值的最小绝对差和对应的三数之和。

	public int threeSumClosest(int[] nums, int target) {
        Arrays.sort(nums);
     	int He,min;
     	if(nums.length<3)return target;
     	min=nums[0]+nums[1]+nums[2];
     	for(int i=0;i<nums.length-2;i++) {
     		if(i!=0) while (nums[i]==nums[i-1]&&i<nums.length-2) i++;
     		for(int j=i+1,k=nums.length-1;j<k;) {
     			He=nums[i]+nums[j]+nums[k];
     			if(He<target) {
     				if(target-He<Math.abs(min-target))min=He;
     				j++;
     			}
     			else if(He>target) {
     				if(He-target<Math.abs(min-target))min=He;
     				k--;
     			}
     			else return target;
     		}
     	}
     	return min;
    }
  • 时 间 复 杂 度 : O ( n 2 ) 时间复杂度:O(n^{2}) O(n2)
  • 空 间 复 杂 度 : O ( 1 ) 空间复杂度:O(1) O(1)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值