18. 四数之和(力扣LeetCode)

文章目录

  • 18. 四数之和
    • 题目描述
    • 双指针

18. 四数之和

题目描述

给你一个由 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

双指针

四数之和,和15.三数之和是一个思路,都是使用双指针法, 基本解法就是在15.三数之和 的基础上再套一层for循环。

但是有一些细节需要注意,例如: 不要判断nums[k] > target 就返回了,三数之和 可以通过 nums[i] > 0 就返回了,因为 0 已经是确定的数了,四数之和这道题目 target是任意值。比如:数组是[-4, -3, -2, -1],target是-10,不能因为-4 > -10而跳过。但是我们依旧可以去做剪枝,逻辑变成nums[i] > target && (nums[i] >=0 || target >= 0)就可以了。

15.三数之和 的双指针解法是一层for循环num[i]为确定值,然后循环内有left和right下标作为双指针,找到nums[i] + nums[left] + nums[right] == 0。

四数之和的双指针解法是两层for循环nums[k] + nums[i]为确定值,依然是循环内有left和right下标作为双指针,找出nums[k] + nums[i] + nums[left] + nums[right] == target的情况,三数之和的时间复杂度是O(n2),四数之和的时间复杂度是O(n3) 。

那么一样的道理,五数之和、六数之和等等都采用这种解法。

对于15.三数之和 双指针法就是将原本暴力O(n3)的解法,降为O(n2)的解法,四数之和的双指针解法就是将原本暴力O(n4)的解法,降为O(n3)的解法。

之前我们讲过哈希表的经典题目:454.四数相加II ,相对于本题简单很多,因为本题是要求在一个集合中找出四个数相加等于target,同时四元组不能重复。

而454.四数相加II是四个独立的数组,只要找到A[i] + B[j] + C[k] + D[l] = 0就可以,不用考虑有重复的四个元素相加等于0的情况,所以相对于本题还是简单了不少!

class Solution {
public:// fourSum 函数用于找出所有和为 target 的唯一四元组。vector<vector<int>> fourSum(vector<int>& nums, int target) {quick_sort(nums, 0, nums.size() - 1);  // 先对数组进行快速排序。vector<vector<int>> result;  // 用于存储所有找到的四元组。// 遍历数组,定位第一个数的位置。for (int i = 0; i < nums.size() - 1; i++) {// 如果当前数已经大于target,并且target是正数,后面的数不可能组成有效四元组。if (nums[i] > target && target >= 0) break;// 如果当前数和前一个数相同,则跳过以避免重复。if (i > 0 && nums[i] == nums[i - 1]) continue;// 遍历数组,定位第二个数的位置。for (int j = i + 1; j < nums.size(); j++) {// 如果前两个数的和已经大于target,并且target是正数,后面的数不可能组成有效四元组。if (nums[i] + nums[j] > target && target >= 0) break;// 如果当前数和前一个数相同,则跳过以避免重复。if (j > i + 1 && nums[j] == nums[j - 1]) continue;// 使用双指针法定位剩下的两个数。int l = j + 1, r = nums.size() - 1;  // l是左指针,r是右指针。while (l < r) {  // 当左指针小于右指针时执行。long z = (long)nums[i] + nums[j] + nums[l] + nums[r];  // 计算四数之和,用long类型防止溢出。// 根据四数之和与目标值的关系,移动指针。if (z > target) {  // 如果四数之和大于目标值,左移右指针。r--;} else if (z < target) {  // 如果四数之和小于目标值,右移左指针。l++;} else {  // 找到一个四元组。// 将这个四元组添加到结果列表中。result.push_back({nums[i], nums[j], nums[l], nums[r]});// 跳过重复的数字。while (l < r && nums[l] == nums[l + 1]) l++;while (l < r && nums[r] == nums[r - 1]) r--;// 移动指针以寻找下一个可能的四元组。l++, r--;}}}}return result;  // 返回所有找到的四元组列表。}private:// 快速排序函数,用于对数组片段进行排序。void quick_sort(vector<int>& n, int l, int r) {// 如果左边界不小于右边界,说明不需要排序。if (l >= r) return;// 初始化指针和基准值。int i = l - 1, j = r + 1, x = n[(l + r) >> 1];while (i < j) {// 左指针右移,直到它指向一个不小于基准值的元素。do i++; while (n[i] < x);// 右指针左移,直到它指向一个不大于基准值的元素。do j--; while (n[j] > x);// 如果i和j没有相遇,交换它们指向的元素。if (i < j) swap(n[i], n[j]);}// 递归地在基准值两边的子区间进行快速排序。quick_sort(n, l, j);quick_sort(n, j + 1, r);}// 归并排序函数,用于对数组片段进行排序。// 注意:这个函数在上面的四数之和函数中被注释掉了,实际上没有被使用。void merge_sort(vector<int>& n, int l, int r) {// 如果左边界不小于右边界,说明不需要排序。if (l >= r) return;// 计算中间索引。int mid = (l + r) >> 1;// 递归地对左半部分和右半部分进行归并排序。merge_sort(n, l, mid);merge_sort(n, mid + 1, r);// 合并两个有序子数组。int i = l, j = mid + 1, k = 0;// 复制两个子数组中的较小元素到临时数组tmp。while (i <= mid && j <= r)if (n[i] < n[j]) tmp[k++] = n[i++];else tmp[k++] = n[j++];// 复制剩下的元素到临时数组tmp。while (i <= mid) tmp[k++] = n[i++];while (j <= r) tmp[k++] = n[j++];// 将临时数组tmp中的元素复制回原数组。for (i = l, j = 0; i <= r; i++, j++) n[i] = tmp[j];}
};

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Log360,引入全新安全与风险管理功能,助力企业积极抵御网络威胁

ManageEngine在其SIEM解决方案中推出了安全与风险管理新功能&#xff0c;企业现在能够更主动地减轻内部攻击和防范入侵。 SIEM 这项新功能为Log360引入了安全与风险管理仪表板&#xff0c;Log360是ManageEngine的统一安全信息与事件管理&#xff08;SIEM&#xff09;解决方案…

【新书推荐】6.1 if语句

第六章 分支结构 计算机语言和人类语言类似&#xff0c;人类语言是为了解决人与人之间交流的问题&#xff0c;而计算机语言是为了解决程序员与计算机之间交流的问题。程序员编写的程序就是计算机的控制指令&#xff0c;控制计算机的运行。借助于编译工具&#xff0c;可以将各种…

Java代码实现基数排序算法(附带源码)

基数排序是一种非比较型整数排序算法&#xff0c;其原理是将整数按位数切割成不同的数字&#xff0c;然后按每个位数分别比较。由于整数也可以表达字符串&#xff08;比如名字或日期&#xff09;和特定格式的浮点数&#xff0c;所以基数排序也不是只能使用于整数。 1. 基数排序…

使用typescript构建Vue2应用

一、vue项目初始化-引入typescript 使用typescript构建vue应用和使用js一样&#xff0c;都是通过vue-cli去初始化并创建一个vue项目&#xff0c;只不过使用typescript构建的时候要在脚手架问卷操作的时候勾选上typescript选项。 二、typescript Vue项目比较 使用typescript构…

大白话介绍循环神经网络

循环神经网络实质为递归式的网络&#xff0c;它在处理时序任务表现出优良的效果&#xff0c;毕竟递归本来就是一步套一步的向下进行&#xff0c;而自然语言处理任务中涉及的文本天然满足这种时序性&#xff0c;比如我们写字就是从左到右一步步来的鸭&#xff0c;刚接触深度学习…

基于hadoop+spark的大规模日志的一种处理方案

概述: CDN服务平台上有为客户提供访问日志下载的功能,主要是为了满足在给CDN客户提供服务的过程中,要对所有的记录访问日志,按照客户定制的格式化需求以小时为粒度(或者其他任意时间粒度)进行排序、压缩、打包,供客户进行下载,以便进行后续的核对和分析的诉求。而且CDN…

xlsx xlsx-style 使用和坑记录

1 安装之后报错 npm install xlsx --savenpm install xlsx-style --save Umi运行会报错 自己代码 import XLSX from "xlsx"; import XLSXStyle from "xlsx-style";const data [["demo1","demo2","demo3","demo4&quo…

好烦,怎么输入拼音的过程也会触发input事件!!!

说在前面 &#x1f388;input输入框大家应该都很熟悉了吧&#xff0c;不知道大家有没有遇到过这样的一种情况&#xff1a;如上图&#xff0c;在中文输入过程中&#xff0c;输入的拼音也会触发input框的input事件&#xff0c;有些时候我们并不希望在中文输入的过程中拼音触发inp…

基于OpenCV灰度图像转GCode的双向扫描实现

基于OpenCV灰度图像转GCode的双向扫描实现 引言激光雕刻简介OpenCV简介实现步骤 1.导入必要的库2. 读取灰度图像3. 图像预处理4. 生成GCode 1. 简化版的双向扫描2. 优化版的双向扫描 5. 保存生成的GCode6. 灰度图像双向扫描代码示例 总结 系列文章 ⭐深入理解G0和G1指令&…

292.Nim游戏

桌子上有一堆石头。 轮流进行自己的回合&#xff0c; 你作为先手 。 每一回合&#xff0c;轮到的人拿掉 1 - 3 块石头。 拿掉最后一块石头的人就是获胜者。 假设你们每一步都是最优解。请编写一个函数&#xff0c;来判断你是否可以在给定石头数量为 n 的情况下赢得游戏。如果可…

Matomo 访问图形显示异常

近期我们的把 PHP 系统完全升级后&#xff0c;访问 Matomo 的站点有关访问的曲线无法显示。 出现的情况如下图&#xff1a; 我们可以看到图片中有关的访问曲线无法显示。 如果具体直接访问链接的话&#xff0c;会有下面的错误信息。 问题和解决 出现上面问题的原因是缺少 ph…

在WebGL中创建动画

前言 在搭建WebGL开发环境中介绍了如何开始使用webgl进行绘制。 本篇文章介绍如何在WebGL中创建动画 动画的定义 动画是一种通过快速显示一系列图像(或帧)模拟运动的技术。 动画的分类 网页上的动画基本分为三类&#xff1a; 声明式动画&#xff0c;如CSS动画和SVG动画&a…

我的创作128纪念日

机缘 起初我写博客是为了记录自己的学习过程,现在也是如此 实战项目中的经验分享日常学习过程中的记录通过文章进行技术交流通过文章加深学习和复习 收获 在创作过程中 获得了400多位粉丝的关注感谢大家的支持阅读数量也达到了3w在博客上认识仲秋大佬,感谢大佬对我的指导,我…

成都软件产业优势明显

是的&#xff0c;成都非常适合软件产业的发展。以下是一些原因&#xff1a; 人才储备丰富&#xff1a;成都拥有众多高等院校和科研机构&#xff0c;为软件产业提供了丰富的人才储备。这些机构培养了大量的软件人才&#xff0c;为成都软件产业的发展提供了有力支持。政策支持&a…

C# 继承的详细介绍和使用

文章目录 前言一、C# 继承的概念&#xff1a;二、继承的基本使用方法三、继承在项目中的具体应用示例四、继承的类型1.公有继承&#xff08;Public Inheritance&#xff09;&#xff1a;2.保护继承&#xff08;Protected Inheritance&#xff09;&#xff1a;3.私有继承&#x…

Java实现康复中心管理系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 普通用户模块2.2 护工模块2.3 管理员模块 三、系统展示四、核心代码4.1 查询康复护理4.2 新增康复训练4.3 查询房间4.4 查询来访4.5 新增用药 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的康复中…

Intellij IDEA各种调试+开发中常见bug

Intellij IDEA中使用好Debug&#xff0c;主要包括如下内容&#xff1a; 一、Debug开篇 ①、以Debug模式启动服务&#xff0c;左边的一个按钮则是以Run模式启动。在开发中&#xff0c;我一般会直接启动Debug模式&#xff0c;方便随时调试代码。 ②、断点&#xff1a;在左边行…

如何在 Microsoft Azure 上部署和管理 Elastic Stack

作者&#xff1a;来自 Elastic Osman Ishaq Elastic 用户可以从 Azure 门户中查找、部署和管理 Elasticsearch。 此集成提供了简化的入门体验&#xff0c;所有这些都使用你已知的 Azure 门户和工具&#xff0c;因此你可以轻松部署 Elastic&#xff0c;而无需注册外部服务或配置…

C语言基础(五)——联合

联合 引言联合的声明联合的声明typedef命名联合 设置联合的值C89&#xff08;标准&#xff09;方式使用.操作符进行指定初始化 联合的内存布局联合的使用场景节省内存资源实际应用案例分析 总结 引言 在学习C语言基础时&#xff0c;联合和结构体是两个经常被拿来比较的概念。虽…

NuxtJs安装Sass后出现ERROR:Cannot find module ‘webpack/lib/RuleSet‘

最近了解NuxtJs时&#xff0c;发现问题比较多&#xff0c;对于初学者来说是件比较头痛的事。这次是安装sass预处理器&#xff0c;通过命令安装后&#xff0c;出现了ERROR&#xff1a;Cannot find module webpack/lib/RuleSet 错误&#xff0c;于是根据之前经验&#xff0c;对版…