LeetCode 15. 三数之和 (关于多数之和问题)

本文介绍了两种方法解决寻找数组中和为0的不重复三元组的问题。方法一是建立哈希表,通过两层遍历来查找满足条件的三元组并避免重复;方法二是采用三指针技巧,通过排序后的数组,调整指针位置找到符合条件的组合。这两种方法都考虑了去重策略,确保结果的唯一性。
摘要由CSDN通过智能技术生成

加油!当自己的实力不能满足自己的目标时,就静下心去学习

  • 总结多数之和问题(两数、三数、四数等)

题目

  • 给你一个包含 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,1,1 ] 和 [ 1 , 1, -2]
  • 解决方法,当第三个数的索引大于第二个数才存入
package leetcodePlan.Base;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class P0015 {

	public static void main(String[] args) {

		int [] nums = {-1,0,1,2,-1,-4} ;
		System.out.println(fun(nums));
	}

	public static List<List<Integer>> fun(int [] nums){
		if(nums.length < 3) {
			return new ArrayList<>() ;
		}
		List<List<Integer>> res = new ArrayList<>() ;
		// 排序
		Arrays.sort(nums); 
		// 构造哈希表
		Integer  tmp ;
		HashMap<Integer,Integer> map = new HashMap<>() ;
		for(int i =0 ; i < nums.length ;i++) { 
			map.put(nums[i], i) ;
		}
		
		for(int i = 0 ; i < nums.length ;i++ ) {
			int target = - nums[i] ;   // 此处 target 为另外两个数之和   
			if( i > 0 && nums[i] == nums[i-1]) {
			    continue ;	
			}
			   for(int j = i+1 ; j <nums.length ;j++) {
				   if(j > i+1 && nums[j] == nums[j-1]) {
					   continue ;
				   }
				   
				   if( (tmp = map.get(target - nums[j])) != null) {   // map.get()   获取 value
					   // 符合要求   最后一个数的序号 大于第二个
					   if(tmp > j) {
						   res.add(new ArrayList<>(Arrays.asList(nums[i],nums[j],nums[tmp]))) ;
					   } else {
						   break ;
					   }
				   }
			   }
		}


		return res ;
	}
	
}

解法二(三指针)

  • 类似于双指针(一前一后一个指针)
  • 首先对数组进行排序
  • 设置前,中、后三个指针(两个在前,一个在后)
  • 假设当三个数之和小于零时,向右移动中指针,只到找到等于零的情况,并将结果保存下来
  • 假设三数字之和大于零的情况下,向左移动后指针,知道中指针和后指针相遇跳出循环。
  • 关于去重问题,我们使用 while 循环,将中指针移动到和之前不同的位置上,前指针同理。如下图

在这里插入图片描述

public static List<List<Integer>> fun2(int [] nums){
		
		List<List<Integer>> res =  new ArrayList<List<Integer>>() ;
		
		if(nums.length < 3) {
			return res ;
		}
		
		Arrays.sort(nums);
		for(int i =0 ; i < nums.length  ; i++) {
			int target = - nums[i] ;
			if( i > 0 && nums[i] == nums[i-1]) continue ;
			
			int l = i+1 ;  // 中指针
			int r = nums.length - 1;
			
			while(l < r) {
				if(nums[l] + nums[r] == target) {
					res.add(new ArrayList<>(Arrays.asList(nums[i],nums[l],nums[r]))) ;
					
					//  去重
					while(l < r && nums[l] == nums[l+1]) l++ ;
					while(l < r && nums[r] == nums[r-1]) r-- ;
					
					l++ ;
					r-- ;
				} else if(nums[l] + nums[r] > target) {
					r-- ;
				} else {
					l++ ;
				}
			}
		}
		
		return res ;
	}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值