当前位置: 首页 > article >正文

leetcode_015_三数之和解析

三数之和解析

题目

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。

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

示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1][-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:
输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0

暴力解法1

使用3重循环暴力解法

package main

import (
	"fmt"
	"sort"
)

// 使用3重for循环
func threeSum(nums []int) [][]int {
	sort.Ints(nums)
	result := make([][]int, 0)
	for i := 0; i < len(nums); i++ {
		for j := 0; j < len(nums); j++ {
			if i == j {
				continue
			}
			for k := 0; k < len(nums); k++ {
				if j == k || i == k {
					continue
				}
				if nums[i]+nums[j]+nums[k] == 0 {
					x := []int{nums[i], nums[j], nums[k]}
					sort.Ints(x)
					result = append(result, x)
				}
			}
		}
	}
	return removeDuplicates(result)
}

func removeDuplicates(slices [][]int) [][]int {
	seen := make(map[string]bool)
	var result [][]int

	for _, slice := range slices {
		// 将子切片转换为字符串作为map的键
		key := fmt.Sprint(slice)
		if !seen[key] {
			seen[key] = true
			result = append(result, slice)
		}
	}
	return result
}

func main() {
	nums := []int{-1, 0, 1, 2, -1, -4}
	res := threeSum(nums)
	fmt.Println(res)
}

暴力解法2

使用优化后的3重循环暴力解法

package main

import (
	"fmt"
	"sort"
)

// 使用3重for循环
func threeSum(nums []int) [][]int {
	sort.Ints(nums)
	result := make([][]int, 0)
	for i := 0; i < len(nums); i++ {
		for j := i + 1; j < len(nums); j++ {
			for k := j + 1; k < len(nums); k++ {
				if nums[i]+nums[j]+nums[k] == 0 {
					result = append(result, []int{nums[i], nums[j], nums[k]})
				}
			}
		}
	}
	return removeDuplicates(result)
}

func removeDuplicates(slices [][]int) [][]int {
	seen := make(map[string]bool)
	var result [][]int

	for _, slice := range slices {
		// 将子切片转换为字符串作为map的键
		key := fmt.Sprint(slice)
		if !seen[key] {
			seen[key] = true
			result = append(result, slice)
		}
	}
	return result
}

func main() {
	nums := []int{-1, 0, 1, 2, -1, -4}
	res := threeSum(nums)
	fmt.Println(res)
}

排序+双指针算法

  • 首先对数组进行排序,排序后固定一个数 nums[i],再使用左右指针指向 nums[i]后面的两端,数字分别为 nums[L] 和 nums[R],计算三个数的和 sum 判断是否满足为 0,满足则添加进结果集

  • 如果 nums[i]大于 0,则三数之和必然无法等于 0,结束循环

  • 如果 nums[i] == nums[i−1],则说明该数字重复,会导致结果重复,所以应该跳过

  • 当 sum == 0 时,nums[L] == nums[L+1] 则会导致结果重复,应该跳过,L++

  • 当 sum == 0 时,nums[R] == nums[R−1] 则会导致结果重复,应该跳过,R−−

  • 当 sum < 0 时,L++

  • 当 sum > 0 时,R–

双指针的左右指针移动条件。

核心思想:排序、双指针移动、跳过重复元素。

跳过重复元素:对于i,在遍历过程中,如果当前元素与前一个元素相同,则跳过它。

对于L,如果当前元素与一个元素(L+1)相同,则跳过它。

对于R,如果当前元素与一个元素(R-1)相同,则跳过它。

func threeSum(nums []int) [][]int {
	if len(nums) < 3 {
		return nil
	}
	sort.Ints(nums)
	result := make([][]int, 0)
	for i := 0; i < len(nums); i++ {
		if nums[i] > 0 {
			break
		}
		if i > 0 && nums[i] == nums[i-1] {
			continue // i去重
		}
		L := i + 1
		R := len(nums) - 1
		for L < R {
			sum := nums[i] + nums[L] + nums[R]
			if sum == 0 {
				result = append(result, []int{nums[i], nums[L], nums[R]})
				for L < R && nums[L] == nums[L+1] {
					L++ // L去重
				}
				for L < R && nums[R] == nums[R-1] {
					R-- // R去重
				}
				L++
				R--
			} else if sum < 0 {
				L++
			} else if sum > 0 {
				R--
			}
		}

	}
	return result
}

http://www.kler.cn/a/324660.html

相关文章:

  • torchvision库在进行图片转换操作中报antialias参数没有显式设置会导致不同图片后端中的值不统一的警告信息
  • Redis五大基本类型——String字符串命令详解(命令用法详解+思维导图详解)
  • 从零开始学习 sg200x 多核开发之 TF 存储卡根文件系统扩容
  • 【Linux:epoll】
  • Java基础——多线程
  • 如何在uniapp中获取和修改Web项目的Cookie
  • Python集成测试详解
  • 工业边缘计算网关和普通网关的区别-天拓四方
  • python基础语法--顺序结构
  • SpringCloud源码:客户端分析(一)- SpringBootApplication注解类加载流程
  • 工业缺陷检测——Windows 10本地部署AnomalyGPT工业缺陷检测大模型
  • naocs注册中心,配置管理,openfeign在idea中实现模块间的调用,getway的使用
  • Python爬虫bs4的基本使用
  • Android平台如何获取CPU占用率和电池电量信息
  • Unity 与虚幻引擎对比:两大游戏开发引擎的优劣分析
  • 【工具变量】无废城市试点DID数据集(2000-2023)
  • 【C++笔记】八、结构体 [ 4 ]
  • 六练习题笔记
  • C++启动其它进程的方式
  • 【运动控制】关于GPIO通用输入口的锁存功能
  • RTX 5090、5080规格完整曝光,来看来看
  • 一起搭WPF界面之界面切换绑定
  • 深度学习之开发环境(CUDA、Conda、Pytorch)准备(4)
  • 基于SSM茶叶科普管理系统JAVA|VUE|SSM计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解
  • PREDATOR: Registration of 3D Point Clouds with Low Overlap
  • DeepSS2GO——基于 CNN 的模型可以根据化学键预测蛋白质的功能