LeetCode - 数组 - 四数之和

题目地址

描述

给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元组元素一一对应,则认为两个四元组重复):

0 <= a, b, c, d < n
a、b、c 和 d 互不相同
nums[a] + nums[b] + nums[c] + nums[d] == target
你可以按 任意顺序 返回答案 。

 

示例 1:

输入:nums = [1,0,-1,0,-2,2], target = 0
输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]
示例 2:

输入:nums = [2,2,2,2,2], target = 8
输出:[[2,2,2,2]]
 

提示:

1 <= nums.length <= 200
-109 <= nums[i] <= 109
-109 <= target <= 109

思路

排序 + 双指针,能有效的提高遍历效率

本人题解

func fourSum(nums []int, target int) [][]int {
   // 排序
	sort.Slice(nums, func(i, j int) bool {
        return nums[i] < nums[j]
    })

	// 因为是四数之和,所以外边两层要通过遍历完成,内两层通过《排序 + 双指针 解两数之和》思路处理
	list := [][]int{}
	
	uniqueFlagMap := map[string]bool{}
	for i1 := 0; i1 < len(nums); i1++ {
		for i2 := i1 + 1; i2 < len(nums); i2++ {
			if l := twoSum(nums, i2+1, len(nums)-1, target-nums[i1]-nums[i2]); len(l) > 0 {
				for _, item := range l {
					// 因为不能出现重复结果,所以此处做了去重处理
					uniqueFlag := fmt.Sprintf("%d%d%d%d", nums[i1], nums[i2], nums[item[0]], nums[item[1]])
					if !uniqueFlagMap[uniqueFlag] {
						uniqueFlagMap[uniqueFlag] = true
						list = append(list, []int{nums[i1], nums[i2], nums[item[0]], nums[item[1]]})
					}
				}
			}
		}
	}
	return list
}

// 求有序数组两数之和方法
func twoSum(nums []int, i3, i4, target int) [][]int {
	list := [][]int{}
	for i3 < i4 {
		t := nums[i3] + nums[i4]
		if t == target {
			list = append(list, []int{i3, i4})
			i3++
		} else if t > target {
			i4--
		} else {
			i3++
		}
	}
	return list
}

LeetCode提交后,得分极差
在这里插入图片描述

优质解法

然后找了得分靠前的一位大佬的解法,果然牛逼的解法是不走寻常路的,先上代码:

func fourSum(nums []int, target int) [][]int {
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] < nums[j]
    })

    n := len(nums)
    var ans [][]int

    for a := 0; a < n-3; a++ {
        if a > 0 && nums[a] == nums[a-1] {
            continue
        }
        if nums[a] + nums[a+1] + nums[a+2] + nums[a+3] > target {
            break
        }
        if nums[a] + nums[n-1] + nums[n-2] + nums[n-3] < target {
            continue
        }
        for b := a+1; b < n-2; b++ {
            if b > a+1 && nums[b] == nums[b-1] {
                continue
            }
            c := b+1
            d := n-1
            for c < d {
                cur := nums[a] + nums[b] + nums[c] + nums[d]
                if cur == target {
                    ans = append(ans, []int{nums[a], nums[b], nums[c], nums[d]})
                    c += 1
                    d -= 1
                    for c < d && nums[c] == nums[c-1] {
                        c += 1
                    }
                    for c < d && nums[d] == nums[d+1] {
                        d -= 1
                    }
                } else if cur < target {
                    c += 1
                } else {
                    d -= 1
                }
            }
        }
    }

    return ans
}

此代码直接借鉴大佬的,有侵权的地方,联系小编

总结

经过对优质解法的分析,得出了以下几点结论:

1、小编的整体思路是没问题的,也就是 ”排序 + 双指针“
2、优质代码增加了以下几点处理:

  • 为了不做去重复处理,在遍历的过程中,就对有可能导致重复的数据做了处理。处理思路是因为数组已经做了排序,所以有可能导致重复结果的数据是挨在一起的,比如 [-1,-1,0,0,-2,-2],如果对第一个-1已经做了处理,第二个-1就不用做处理了,直接跳过即可
func fourSum(nums []int, target int) [][]int {
    sort.Slice(nums, func(i, j int) bool {
        return nums[i] < nums[j]
    })

    n := len(nums)
    var ans [][]int

    for a := 0; a < n-3; a++ {
    	// 跳过有可能导致重复结果的数据
        if a > 0 && nums[a] == nums[a-1] {
            continue
        }
        if nums[a] + nums[a+1] + nums[a+2] + nums[a+3] > target {
            break
        }
        if nums[a] + nums[n-1] + nums[n-2] + nums[n-3] < target {
            continue
        }
        for b := a+1; b < n-2; b++ {
        	// 跳过有可能导致重复结果的数据
            if b > a+1 && nums[b] == nums[b-1] {
                continue
            }
            c := b+1
            d := n-1
            for c < d {
                cur := nums[a] + nums[b] + nums[c] + nums[d]
                if cur == target {
                    ans = append(ans, []int{nums[a], nums[b], nums[c], nums[d]})
                    c += 1
                    d -= 1
                    // 跳过有可能导致重复结果的数据
                    for c < d && nums[c] == nums[c-1] {
                        c += 1
                    }
                    // 跳过有可能导致重复结果的数据
                    for c < d && nums[d] == nums[d+1] {
                        d -= 1
                    }
                } else if cur < target {
                    c += 1
                } else {
                    d -= 1
                }
            }
        }
    }

    return ans
}
  • 对有序数组做掐头去尾处理
 for a := 0; a < n-3; a++ {
	// 去尾处理
	if nums[a]+nums[a+1]+nums[a+2]+nums[a+3] > target {
		break
	}

	// 掐头处理
	if nums[a]+nums[n-1]+nums[n-2]+nums[n-3] < target {
		continue
	}
}

经过这两步的优化,极大程度降低了遍历的次数,同时也缩短了每次遍历的耗时,所以整体上优化了耗时

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/644542.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机器学习与大模型】驱动下的应用图像识别与处理

摘要&#xff1a; 本文深入探讨了机器学习在图像识别与处理领域的应用&#xff0c;特别是在大模型的推动下所取得的巨大进展。详细阐述了图像识别与处理的基本原理、关键技术&#xff0c;以及机器学习算法和大模型如何提升其性能和准确性。通过实际案例分析了其在多个领域的广泛…

[WUSTCTF2020]level3

base64换表 但是这的表有一个引用 模拟执行 #DRKCTF{}aABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/ flag[ord(i) for i in a] for i in range(0,10):flag[i],flag[19-i]flag[19-i],flag[i] for i in flag:print(chr(i),end)新表 TSRQPONMLKJIHGFEDCBAU…

技术速递|无障碍应用程序之旅:键盘可访问性和 .NET MAUI

作者&#xff1a;Rachel Kang 排版&#xff1a;Alan Wang 首先让我们一起来看看您的应用程序是否支持键盘访问&#xff1a; 启动您的其中一个应用。如果您的设备尚未连接物理键盘&#xff0c;请连接物理键盘。像平常一样导航您的应用程序&#xff0c;并且仅使用键盘来执行此操…

DI-engine强化学习入门(三)DI-ZOO强化学习环境搭建与示例运行——Atari

Atari是一家知名的电子游戏公司&#xff0c;成立于1972年&#xff0c;是早期电子游戏产业的先驱之一。在强化学习领域&#xff0c;提到Atari通常指的是Atari 2600游戏的一系列环境&#xff0c;这些环境是用于开发和测试强化学习算法的标准平台。 Atari 2600 强化学习环境概述 …

ABC354学习笔记

高桥有一棵植物&#xff0c;这个植物在第 0 0 0 天时高度为 0 c m 0\,\mathrm{cm} 0cm&#xff0c;此后的第 i i i 天&#xff0c;他的植物会增高 2 i c m 2^i\,\mathrm{cm} 2icm。 高桥身高为 H c m H\,\mathrm{cm} Hcm。 高桥想知道在第几天&#xff0c;他的植物的高度会…

Vue移动端登录页面

使用的是vant组件&#xff0c;引用和使用组件请去官网学习&#xff0c;链接↓vant组件官网 <div class"center"><!-- 背景图片 --><div class"background"><imgsrc"/assets/background.jpg"width"100%"heigh…

STL题单总结

下周争取全部刷掉 牛客 知乎推荐的题 收藏的文章1 收藏的文章2 收藏的文章3 洛谷题单

ICQ 将于 6 月关闭,这是一种奇怪的方式,发现它在 2024 年仍然活跃

你知道ICQ还活着吗&#xff1f;不过&#xff0c;不要太兴奋;它将永远消失。 还记得ICQ吗&#xff1f;如果你这样做了&#xff0c;你可能会记得它是AOL在1998年购买的Messenger客户端&#xff0c;就在Yahoo Instant Messager和MSN Messenger加入竞争的时候。然后Skype出现了&…

嵌入式全栈开发学习笔记---C语言笔试复习大全23

目录 联合体 联合体的定义 联合体的长度 如果来判断设备的字节序&#xff1f; 如何把大端数据转换成小端数据&#xff1f; 枚举 枚举的定义 上一篇复习了结构体&#xff0c;这一节复习联合体和枚举。 说明&#xff1a;我们学过单片机的一般都是有C语言基础的了&#xff…

【资讯】5月巴塞罗那,东胜物联边缘计算网关亮相IOTSWC AWS展台

2024年5月21-23日&#xff0c;物联网解决方案世界大会 IOT SWC 在巴塞罗那举行&#xff0c;这是数字化转型趋势和颠覆性技术的顶级盛会。 作为AWS的硬件合作伙伴&#xff0c;东胜物联网边缘计算网关DSGW-210将在AWS展台1号馆展出&#xff0c;欢迎大家前来参观。 此次东胜在AW…

【Linux】写时拷贝技术COW (copy-on-write)

文章目录 Linux写时拷贝技术(copy-on-write)进程的概念进程的定义进程和程序的区别PCB的内部构成 程序是如何被加载变成进程的&#xff1f;写时复制&#xff08;Copy-On-Write, COW&#xff09;写时复制机制的原理写时拷贝的场景 fork与COWvfork与fork Linux写时拷贝技术(copy-…

阿里云、百度云和移动云的对象存储横向性能对比

文章目录 前言一、对比测试的方法和标准A. 测试环境的设置 二、对比测试的结果A、阿里云OSS测试结果2.B. 百度云结果C. 移动云结果分析与结论 总结 前言 在企业的数字化转型进程中&#xff0c;我们观察到越来越多的公司将其IT基础设施迁移到云端。随着企业业务的持续运营&…

5.Redis之常用数据结构单线程模型

围绕每个数据结构介绍相关命令当前版本的redis支持10个数据类型 Redis 底层在实现上述数据结构的时候,会在源码层面,针对上述实现进行特定的优化,来达到 节省时间/节省空间 效果,内部的具体实现的数据结构&#xff08;编码方式&#xff09;,还会有变数redis 承诺,现在我这有个 …

pikachu靶场中的CSRF、SSRF通关

目录 1、CSRF介绍 2、CSRF&#xff08;get&#xff09; 3、CSRF&#xff08;post&#xff09; 4、CSRF Token 5、SSRF介绍 6、SSRF&#xff08;curl&#xff09; 7、SSRF&#xff08;file_get-content&#xff09; 8、CSRF与SSRF的区别 最近在学习CSRF、SSRF漏洞&#…

LeetCode HOT 100:3. 无重复字符的最长字串

1. 链接 . - 力扣&#xff08;LeetCode&#xff09; 2. 题目描述 3. 题解 方法一&#xff1a;滑动窗口 哈希表 根据题意&#xff1a; 1. 遍历所有可能的子串——利用滑动窗口表示子串&#xff1b; 2. 保证滑动窗口内不包含重复字符——需要哈希表map记录字符出现的下标。…

PostgreSQL基本使用Schema

参考文章&#xff1a;PostgreSQL基本使用&#xff08;3&#xff09;Schema_pg数据库查询schema-CSDN博客 PostgreSQL 模式&#xff08;Schema&#xff09;可以理解为是一个表的集合&#xff08;或者所属者&#xff09;。 例如&#xff1a;在 MySQL 中&#xff0c;Scheam 是库&…

etcd集群部署

1.etcd介绍 1.1 什么是etcd etcd的官方定义如下: A distributed, reliable key-value store for the most critical data of distributed systemetcd是一个Go语言编写的分布式、高可用的一致性键值存储系统,用于提供可靠的分布式键值(key value)存储、配置共享和服务发现等…

Nginx-狂神说

Nginx概述 公司产品出现瓶颈&#xff1f; 我们公司项目刚刚上线的时候&#xff0c;并发量小&#xff0c;用户使用的少&#xff0c;所以在低并发的情况下&#xff0c;一个jar包启动应用就够了&#xff0c;然后内部tomcat返回内容给用户。 但是慢慢的&#xff0c;使用我们平台…

C++ 常用UI库

AWTK github gitee doc scons 类似RT-Thread element github C Cross platfrom C GUI libraries&#xff0c;QT可替代方案。调试包 SDL GUI cegui 创作不易&#xff0c; 小小的支持一下吧&#xff01;

如何在Windows 10上对硬盘进行碎片整理?这里提供步骤

随着时间的推移&#xff0c;由于文件系统中的碎片&#xff0c;硬盘驱动器可能会开始以较低的效率运行。为了加快驱动器的速度&#xff0c;你可以使用内置工具在Windows 10中对其进行碎片整理和优化。方法如下。 什么是碎片整理 随着时间的推移&#xff0c;组成文件的数据块&a…