当前位置: 首页 > 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/news/324660.html

相关文章:

  • 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 的模型可以根据化学键预测蛋白质的功能
  • JPA + Thymeleaf 增删改查
  • 【Element-UI】实现el-drawer抽屉的左右拖拽宽度
  • ​美​团​一​面​-​2​
  • 《中国电子报》报道: 安宝特AR为产线作业者的“秘密武器
  • 一种用于常开型智能视觉感算系统的极速高精度模拟减法器
  • c++模拟真人鼠标轨迹算法
  • css实现自定义静态进度条-vue2
  • 【Elasticsearch】-dense_vector与hnsw的含义
  • idea 创建多模块项目
  • 探索基因奥秘:汇智生物如何利用组蛋白甲基化修饰测序技术革新农业植物基因组研究?