C++算法练习-day19——18.四数之和

题目来源:. - 力扣(LeetCode)

题目思路分析

题目要求在给定的整数数组 nums 和一个目标值 target 中,找出所有独特的四元组(四个数),使得这四个数的和等于 target。需要注意的是,解集中的数字不能重复。

为了解决这个问题,我们可以采用一种优化的四数之和算法。具体思路如下:

  1. 排序:首先对数组进行排序,这有助于我们跳过重复的数字,并且可以使用双指针技术来减少时间复杂度。
  2. 固定前两个数:通过两层循环分别固定前两个数(记为 nums[a] 和 nums[b]),其中 a 从 0 遍历到 n-4(确保至少还有三个数可以选择),b 从 a+1 遍历到 n-3
  3. 跳过重复数字:在每层循环的开始,检查当前数字是否与上一个数字相同,如果是,则跳过,以避免重复的四元组。
  4. 提前终止:在固定 nums[a] 和 nums[b] 后,可以通过检查当前四个数的最小和与最大和是否满足目标值 target 来提前终止循环,从而减少不必要的计算。
    • 如果当前四个数的最小和(即 nums[a] + nums[a+1] + nums[a+2] + nums[a+3])大于 target,则无需继续遍历 b 及其后的数,因为后面的和会更大。
    • 如果当前四个数的最大和(即 nums[a] + nums[b] + nums[n-2] + nums[n-1],注意这里 b 还未固定到最大值)小于 target,则可以跳过当前的 a,直接检查下一个 a,因为即使 b 取最大值,和仍然小于 target
  5. 双指针寻找后两个数:对于固定的 nums[a] 和 nums[b],使用双指针 c 和 d 分别从 b+1 和数组末尾开始,向中间移动,寻找满足 nums[a] + nums[b] + nums[c] + nums[d] == target 的组合。
  6. 调整指针:如果当前和小于 target,则 c 向右移动;如果当前和大于 target,则 d 向左移动。
  7. 记录结果:每当找到一个满足条件的四元组时,将其添加到结果集中。

代码:

#include <vector>  
#include <algorithm>  using namespace std;  class Solution {  
public:  vector<vector<int>> fourSum(vector<int>& nums, int target) {  vector<vector<int>> ans;  int n = nums.size();  if (n < 4) {  return ans; // 如果数组长度小于4,无法找到四元组,直接返回空结果  }  sort(nums.begin(), nums.end()); // 对数组进行排序  // 固定前两个数  for (int a = 0; a < n - 3; ++a) {  // 跳过重复的数字  if (a > 0 && nums[a] == nums[a - 1]) {  continue;  }  // 提前终止:如果当前四个数的最小和大于target,则无需继续遍历  if ((long)nums[a] + nums[a + 1] + nums[a + 2] + nums[a + 3] > target) {  break;  }  // 提前终止:如果当前a能取到的最大和小于target,则跳过当前的a  if ((long)nums[a] + nums[n - 3] + nums[n - 2] + nums[n - 1] < target) {  continue;  }  for (int b = a + 1; b < n - 2; ++b) {  // 跳过重复的数字  if (b > a + 1 && nums[b] == nums[b - 1]) {  continue;  }  // 提前终止:如果当前四个数的最小和大于target,则无需继续遍历b及其后的数  if ((long)nums[a] + nums[b] + nums[b + 1] + nums[b + 2] > target) {  break;  }  // 提前终止:如果当前b能取到的最大和小于target,则跳过当前的b(但这里其实可以省略,因为外层a已经检查过了)  // 但为了保持逻辑完整性,还是保留了这个检查  if ((long)nums[a] + nums[b] + nums[n - 2] + nums[n - 1] < target) {  continue;  }  int d = n - 1; // 初始化右指针  // 固定第三个数,移动第四个数  for (int c = b + 1; c < n - 1; ++c) {  // 跳过重复的数字  if (c > b + 1 && nums[c] == nums[c - 1]) {  continue;  }  long sum = (long)nums[a] + nums[b] + nums[c] + nums[d]; // 计算当前和  // 如果当前和大于目标值,移动右指针  while (c < d && sum > target) {  --d;  sum = (long)nums[a] + nums[b] + nums[c] + nums[d]; // 更新当前和  }  // 如果当前指针相遇,则无法再找到符合条件的四元组,跳出循环  if (c == d) {  break;  }  // 如果找到符合条件的四元组,记录结果  if (sum == target) {  ans.push_back({nums[a], nums[b], nums[c], nums[d]});  }  }  }  }  return ans; // 返回结果集  }  
};
知识点摘要
  1. 排序:排序是处理数组问题时的常用技巧,有助于跳过重复元素和使用双指针技术。
  2. 双指针:在处理三个或更多数的和问题时,双指针技术可以大大减少时间复杂度。
  3. 边界条件:在处理数组问题时,要特别注意数组长度、指针移动范围等边界条件。
  4. 跳过重复:在固定某些数时,通过检查当前数是否与上一个数相同来跳过重复的组合。
  5. 提前终止:通过检查当前四个数的最小和与最大和是否满足目标值 target 来提前终止循环,减少不必要的计算。

补充:用(long)转换四数之和的结果是为了防止四数之和超过int的范围 

四数之和问题是一个经典的算法问题,通过排序、双指针、跳过重复元素和提前终止等技巧,我们可以高效地解决这个问题。在本文中,我们详细分析了题目的思路,并给出了带有详细注释的代码实现。通过这些技巧,我们可以显著减少算法的时间复杂度,提高程序的运行效率。同时,这些技巧在处理其他类似的数组问题时也具有一定的参考价值。希望读者能够深入理解这些技巧,并在实际应用中灵活运用。

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

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

相关文章

Svelte 5 正式发布:新一代前端框架!

10 月 22 日&#xff0c;Svelte 5 正式发布&#xff01;该版本带来的更新主要包括&#xff1a; 重写框架&#xff1a;Svelte 5 是从头开始重写的&#xff0c;使得应用更快、更小、更可靠&#xff0c;并且代码更一致和符合习惯。 向后兼容&#xff1a;Svelte 5 几乎完全向后兼容…

把代码绑定到WPF中的textblock中

在WPF中&#xff0c;将数据绑定到TextBlock控件中是一个常见的操作&#xff0c;这样可以动态显示数据源中的数据。以下是如何将数据绑定到TextBlock的步骤&#xff1a; 定义数据源&#xff1a; 首先&#xff0c;你需要有一个数据源&#xff0c;它可以是一个属性&#xff0c;这个…

一个简单的例子,说明Matrix类的妙用

在Android、前端或者别的平台的软件开发中&#xff0c;有时会遇到类似如下需求&#xff1a; 将某个图片显示到指定的区域&#xff1b;要求不改变图片本身的宽高比&#xff0c;进行缩放&#xff1b;要求最大限度的居中填充到显示区域。 以下示意图可以简单描绘该需求 以Androi…

ETL、ELT和反向ETL都有什么不同?怎么选择?

数据处理是现代企业中不可或缺的一部分。随着数据量的不断增长&#xff0c;如何高效地处理、转换和加载数据变得尤为重要。本文将介绍三种常见的数据处理方式&#xff1a;ETL、ELT和反向ETL&#xff0c;帮助读者更好地理解和选择适合自己业务需求的方式。 一、ETL 定义&#…

Apache POI—读写Office格式文件

Apache POI 是一个开源的 Java 库&#xff0c;用于读写 Microsoft Office 格式的文件&#xff0c;主要包括 Excel、Word 和 PowerPoint 等文档。POI 对 Excel 文件的支持最为完善&#xff0c;通过 POI 可以方便地进行 Excel 文件的创建、编辑、读取等操作。 1. Apache POI 简介…

深入理解 SQL 中的 WITH AS 语法

在日常数据库操作中&#xff0c;SQL 语句的复杂性往往会影响到查询的可读性和维护性。为了解决这个问题&#xff0c;Oracle 提供了 WITH AS 语法&#xff0c;这一功能可以极大地简化复杂查询&#xff0c;提升代码的清晰度。本文将详细介绍 WITH AS 的基本用法、优势以及一些实际…

面对复杂的软件需求:5大关键策略!

面对软件需求来源和场景的复杂性&#xff0c;有效地管理和处理需求资料是确保项目成功的关键&#xff0c;能够提高需求理解的准确性&#xff0c;增强团队协作和沟通&#xff0c;降低项目风险&#xff0c;提高开发效率。反之&#xff0c;项目可能面临需求理解不准确、团队沟通不…

Lucas带你手撕机器学习——套索回归

好的&#xff0c;下面我将详细介绍套索回归的背景、理论基础、实现细节以及在实践中的应用&#xff0c;同时还会讨论其优缺点和一些常见问题。 套索回归&#xff08;Lasso Regression&#xff09; 1. 背景与动机 在机器学习和统计学中&#xff0c;模型的复杂性通常会影响其在…

从简单的demo开始让您逐步了解GetX的用法

目录 前言 一、从demo开始体现下Getx的用法 二、从最简单的功能开始 1.新建一个Flutter工程 2.GetX初体验 1.路由跳转 1.普通路由跳转 2.跳转并从堆栈中销毁当前页面 3.跳转并销毁之前所有页面 4.跳转以及传值 2.更方便的实现SnackBar、Dialog、BottomSheet 三、Ge…

项目文章 | 药学TOP期刊PRChIP-seq助力揭示激酶LIMK2促进梗死不良重构的机制

急性心肌梗死&#xff08;MI&#xff09;是全球死亡的主要原因&#xff0c;尽管MI的死亡率有所下降&#xff0c;缺血性心力衰竭的发病率却呈上升趋势。这一现象提示我们&#xff0c;尽管在急救和治疗急性心肌梗死方面取得了进展&#xff0c;但心脏在梗死后的长期功能恢复仍然是…

Prometheus新手必看:三步搞定基于文件、DNS和Consul的服务发现

一、基于文件的服务发现 基于文件的服务发现是仅仅略优于静态配置的服务发现方式&#xff0c;它不依赖于任何平台或第三方服务&#xff0c;因而也是最简单和通用的服务发现方式。Prometheus Server定期从文件中加载Target信息文件可使用JSON或YAML格式&#xff0c;它含有定义的…

opencv学习笔记(3):图像和视频的读取(C++)

我们知道&#xff0c;OpenCV是一个计算机视觉的开源库&#xff0c;它最基本也最重要的功能肯定是对图像和视频的处理。这个章节学习基本的图像和视频的读取。 1. 图像读取与保存&#xff1a; 1.1 图像读取&#xff1a; 在OpenCV中&#xff0c;使用cv::imread()函数来读取和加…

成品气楼参考图集有哪些?盘点5本实用图集,你都知道哪几本

成品气楼也被称为通风天窗、自然通风器、屋顶通风器&#xff0c;是帮助厂房、商业建筑体等建筑通风换气的大型设备&#xff0c;被广泛应用在各行各业。想要成品气楼的通风、采光、排烟作用得到充分发挥&#xff0c;需选型合理&#xff0c;配置合适&#xff0c;安装得当&#xf…

介绍 Docker 的基本概念和优势,以及在应用程序开发中的实际应用。(AI)

Docker是一种开源的容器化平台&#xff0c;可以将应用程序和其依赖项打包成一个独立的可运行的容器。Docker的基本概念包括以下几个方面&#xff1a; 1. 容器&#xff1a;容器是一个独立的、可运行的软件包&#xff0c;包含应用程序和其依赖项。容器化可以将应用程序与底层操作…

v4.7+版本用户充值在交易统计中计算双倍的问题修复

app/services/statistic/TradeStatisticServices.php 文件中 $whereInRecharge[recharge_type] no_system; $whereInRecharge[recharge_type] system; app/model/user/UserRecharge.php 中 修改此搜索器内容 public function searchRechargeTypeAttr($query, $value){ if…

二百七十一、Kettle——ClickHouse增量导入数据清洗记录表

一、目的 在完成错误数据表任务后&#xff0c;需要对每条错误数据的错误字段及其字段值进行分析 Hive中原有SQL语句和ClickHouse现有SQL语句很大不同 二、Hive中原有代码 2.1 表结构 --31、静态排队数据清洗记录表 create table if not exists hurys_db.dwd_data_clean_…

python编程-装饰器

目录 一、装饰器的概念 装饰器与设计模式的关联 二、装饰器的基本结构和语法 1. 函数装饰器 定义装饰器函数&#xff1a; 应用装饰器到函数&#xff1a; 方式一&#xff1a;使用符号&#xff08;语法糖&#xff09; 方式二&#xff1a;手动调用装饰器函数 函数装饰器的…

vue3+ts实时播放视频,视频分屏

使用vue3以及播放视频组件Jessibuca Jessibuca地址 使用循环个数来实现分屏 效果图&#xff0c;四屏 九屏 dom代码 <div class"icon"><div class"icon-box"><span class"text">分屏&#xff1a;</span><el-icon …

银行信贷风控专题:Python、R 语言机器学习数据挖掘应用实例合集:xgboost、决策树、随机森林、贝叶斯等

全文链接&#xff1a;https://tecdat.cn/?p38026 原文出处&#xff1a;拓端数据部落公众号 分析师&#xff1a;Fanghui Shao 在当今金融领域&#xff0c;风险管控至关重要。无论是汽车贷款违约预测、银行挖掘潜在贷款客户&#xff0c;还是信贷风控模型的构建&#xff0c;以及…

NF和C-BRUNO的区别

C-BRUNO与标准化流&#xff08;Normalizing Flow&#xff09;模型有一定的相似性&#xff0c;但它们在目标、应用和实现细节上存在明显的区别。以下是两者之间的主要区别&#xff1a; 1. 目标和应用领域 标准化流模型&#xff1a;标准化流的目标是通过一系列可逆变换将复杂的…