算法练习-四数之和(思路+流程图+代码)

难度参考

        难度:中等

        分类:数组

        难度与分类由我所参与的培训课程提供,但需要注意的是,难度与分类仅供参考。且所在课程未提供测试平台,故实现代码主要为自行测试的那种,以下内容均为个人笔记,旨在督促自己认真学习。

题目

        给定一个包含n个整数的数组nums和一个目标值target,判断nums中是否存在四个元素a,b,c和d,使得a+b+c+d的值与target相等?找出所有满足条件且不重复的四元组。
        示例1:
        输入:nums=[1,0,-1,0,-2,2]和target=0
        输出:[[-1,0,0,1],[-2,-1,1,2],[-2,0,0,2]]
        额外要求:
        ·答案中不可以包含重复的四元组

思路

  1. 排序: 首先将数组nums排序。排序是为了后面能够方便地跳过重复的元素。

  2. 循环遍历: 使用两层嵌套循环遍历数组,外层循环选择第一个数字a,内层循环选择第二个数字b

  3. 双指针寻找: 内层循环固定了ab之后,使用一对双指针leftright(分别初始化为b之后的下一个元素和数组末尾的元素)来查找剩下的两个数字。

  4. 移动双指针: 如果a + b + nums[left] + nums[right]的和小于target,则移动left指针;如果和大于target,则移动right指针;如果和等于target,则将这四个元素作为一组加入结果集。

  5. 跳过重复元素: 在循环和双指针移动的过程中,每当我们要移动某个指针时,如果下一个数字与当前数字相同,那么我们就继续移动指针,直到遇到一个不同的数字为止。这样可以避免重复的组合加入结果集。

  6. 返回结果: 最后返回存放所有四元组的结果集。

示例

        假设我们得到的输入是nums = [1, 0, -1, 0, -2, 2],并且target = 0

  1. 排序:
    排序后的nums数组将是[-2, -1, 0, 0, 1, 2]

  2. 循环遍历双指针寻找:

    a. 在最外层循环中,我们首先选择-2作为a。此时i=0

    b. 在第二层循环中,我们选择-1作为b。此时j=1

    c. 现在我们将left设为j+1,即2的位置,right设为数组的最后一个元素的位置,即2的位置。

    d. 进行双指针查找,我们开始检查sum = a + b + nums[left] + nums[right]是否等于target

  3. 移动双指针:

    a. 第一次计算得到sum = -2 + (-1) + 0 + 2 = -1,这比target小,所以我们移动左指针left向右一位。

    b. 现在left在第三个0的位置上,我们再次计算得到sum = -2 + (-1) + 0 + 2 = -1,依然比target小,所以我们再次移动左指针。

    c. 左指针不断右移,直到leftright指向同一个元素或者leftright左边时停止。

  4. 找到合适的组合:

    a. 如果在移动指针的过程中找到sum = target,例如我们发现nums[0] + nums[1] + nums[3] + nums[5] = -2 + (-1) + 0 + 2 = 0,我们加入这个组合[-2, -1, 0, 2]到结果集中。

  5. 跳过重复元素:

    如果有重复的元素,例如在nums = [1, 0, -1, 0, -2, 2]排序后的数组中从第三个元素开始到第四个元素是0,我们在寻找组合[-1, 0, 0, 1]之后,需要跳过所有接下来的相同的数字(这里是0),以避免重复的组合被加入结果集。

梳理

        这种解法有效地解决了四数之和的问题,它使用了以下几个关键的处理方式:

  1. 排序: 这是双指针方法能够工作的前提。通过对原数组进行排序,我们能够以线性的方式(通过移动指针)来改变所选元素组合的和(sum)。如果和小了,我们可以通过移动左指针向右方向增大;如果和大了,可以通过移动右指针向左方向减小。

  2. 双指针寻找: 这是减少算法复杂度的关键。对于已排序的数组,固定两个数后,可以在O(n)的时间内通过双指针找到符合条件的其他两个数,该策略避免了简单粗暴的四层循环(O(n^4))。

  3. 跳过重复元素: 这种处理方式利用了数组已排序的性质。当固定住一个或多个数字时,为了避免重复出现解,需要跳过数组中接下来的相同数字。这种去重是通过在循环和双指针移动的过程中检测相邻数字是否相同来实现的。

        这个解法借鉴了三数之和问题(3Sum)的经典解法,扩展到了四个数字,使得该问题的时间复杂度从O(n^4)降低到了O(n^3)。它有效地运用了双指针技巧来减少对时间复杂度的需求,同时也利用了排序以及跳过重复元素来确保找到所有可能的唯一结果。这种方法在解决类似的求和问题中是相当常见和高效的。

        三数之和:算法练习-三数之和(思路+流程图+代码)-CSDN博客

代码

#include <iostream> // 导入输入输出流的库
#include <vector>   // 导入向量容器的库
#include <algorithm> // 导入算法库(包括sort)using namespace std; // 使用标准命名空间以简化代码// fourSum函数,找出所有和为target的四元组合
vector<vector<int>> fourSum(vector<int>& nums, int target) {// 初始化返回的结果集vector<vector<int>> result;// 当输入向量的大小小于4时,不可能有四个数的组合,直接返回空的结果集if (nums.size() < 4) return result;// 对输入向量进行排序,为了后续操作可以采用双指针的方法sort(nums.begin(), nums.end());// 第一层循环,确定第一个数for (unsigned int i = 0; i < nums.size() - 3; ++i) {// 如果当前数字和之前的数字相同,则跳过,以避免产生重复结果if (i > 0 && nums[i] == nums[i-1])continue;// 第二层循环,确定第二个数for (unsigned int j = i + 1; j < nums.size() - 2; ++j) {// 如果当前数字和之前的数字相同,则跳过,以避免产生重复结果if (j > i + 1 && nums[j] == nums[j-1])continue;// 第三层循环采用双指针方法,确定剩下的两个数int left = j + 1;  // 左指针初始化int right = nums.size() - 1;  // 右指针初始化// 使用双指针在剩余数组中寻找合适的两个数字,使得这四个数字之和为targetwhile (left < right) {// 计算当前四个数的和int sum = nums[i] + nums[j] + nums[left] + nums[right];// 如果四数之和等于目标和,则将它们作为一个四元组添加到结果集中if (sum == target) {// 添加到结果集result.push_back({nums[i], nums[j], nums[left], nums[right]});// 为了避免添加重复的四元组,需要将左指针移到下一个不同的数while (left < right && nums[left] == nums[left+1]) left++;// 同样的,将右指针移到上一个不同的数while (left < right && nums[right] == nums[right-1]) right--;// 将左、右指针各自移到下一个位置left++;right--;// 如果四数之和小于目标和,则将左指针右移,增加总和} else if (sum < target) {left++;// 如果四数之和大于目标和,则将右指针左移,减少总和} else {right--;}}}}// 返回最终结果集return result;
}// 辅助函数,用于打印四数之和的结果
void printResult(const vector<vector<int>>& res) {cout << "["; // 开始打印输出结果// 遍历所有的四元组并打印它们for (const auto &v : res) {cout << "[";for (int i = 0; i < v.size(); ++i) {cout << v[i];if (i < v.size() - 1) cout << ","; // 用逗号分隔同一个四元组的数}cout << "],"; // 结束四元组的打印}if (!res.empty()) cout << "\b"; // 如果结果集不为空,则去掉最后一个多余的逗号cout << "]" << endl; // 结束打印输出结果
}int main() {// 创建一个示例向量vector<int> nums = {1, 0, -1, 0, -2, 2};// 定义目标和int target = 0;// 调用函数并保存结果vector<vector<int>> res = fourSum(nums, target);// 打印结果printResult(res); // main函数正常退出return 0;
}

打卡

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

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

相关文章

“过年买年货,花光了我的年终奖”

【潮汐商业评论/原创】 前脚刚进家门&#xff0c;后脚快递电话一个接着一个。 临近春节&#xff0c;Julia是提前批回家的年轻人&#xff0c;与Julia一同到家的还有她的年货。上至大小家电&#xff0c;下到坚果零食&#xff0c;短短几天快递就堆满了客厅。 吃的喝的还能理解&…

MySQL的优化

优化MySQL的几点&#xff1a; 从设计上优化 从查询上优化 从索引上优化 从存储上优化 1&#xff0c;SQL的执行频率 MySQL客户端连接成功后&#xff0c;通过show [session/global] status命令可以查看服务器状态信息。通过查看状态信息可以查看对当前数据库的主要操作类型…

【01】判断素数/质数(C语言)

目录 &#xff08;1&#xff09;素数特点&#xff1a;只能被1和本身整除 &#xff08;2&#xff09;代码如下&#xff1a; &#xff08;3&#xff09;运行结果如下 ​编辑 &#xff08;4&#xff09;函数引申 &#xff08;1&#xff09;素数特点&#xff1a;只能被1和本身…

数字图像处理(实践篇)四十三 OpenCV-Python 使用SURF算法检测图像上的特征点的实践

目录 一 SURF算法概述 1 积分图 2 SURF算法 3 SIFT与SURF 二 涉及的函数 三 实践 一 SURF算法概述

在容器中使用buildah构建镜像

简介 buildah是一个构建OCI标准镜像的工具&#xff0c;可以用来替代docker build 在常见的linux发行版中可直接通过包管理工具安装使用 # centos yum install buildah# ubuntu/debian apt install buildah# alpine apk add buildah其他发行版安装方法详见 github&#xff0c…

Django通过Json配置文件分配多个定时任务

def load_config():with open("rule.json", rb)as f:config json.load(f)return configdef job(task_name, config, time_interval):# ... 通过task_name判断进行操作if task_name get_data_times:passdef main():config load_config()for task_name, task_value…

C++——stack与queue与容器适配器

1.stack和queue的使用 1.1stack的使用 栈这种数据结构我们应该挺熟了&#xff0c;先入后出&#xff0c;只有一个出口(出口靠栈顶近)嘛 stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类&#xff0c;这些容器类应该支持以操作&#xff1a; empty&#xff1…

专业知识库:中小型企业必备的高效工具

在如今这个信息爆炸的时代&#xff0c;知识管理已经成为了企业运营的重要环节。特别是对于中小型企业来说&#xff0c;如何有效地管理公司内部的知识&#xff0c;提高工作效率&#xff0c;已经成为了一个亟待解决的问题。在这篇文章中&#xff0c;我将向大家介绍一种能够帮助企…

Python轴承故障诊断入门教学

目录 往期精彩内容&#xff1a; 1 工作室实验平台介绍 2 轴承故障诊断教程—数据集 3 轴承故障诊断教程—算法模型 3.1 振动分析方法 3.2 频域特征提取 3.3 时域特征提取 3.4 模型基础的机器学习方法 3.5 深度学习方法 3.6 时频域融合方法 3.7 信号重构方法 3.8 基…

Linux-----文本三剑客补充~

一、模糊匹配 模糊匹配用 ~ 表示包含&#xff0c;!~表示不包含 1、匹配含有root的列 [rootlocalhost ~]#awk -F: /root/ /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin [rootlocalhost ~]#awk -F: $1~ /root/ /etc/passw…

知名开发工具RubyMine全新发布v2023.3——支持AI Assistant

RubyMine 是一个为Ruby 和 Rails开发者准备的 IDE&#xff0c;其带有所有开发者必须的功能&#xff0c;并将之紧密集成于便捷的开发环境中。 RubyMine v2023.3正式版下载 新版本改进AI Assistant支持、Rails应用程序和引擎的自定义路径、对Rails 7.1严格locals的代码洞察、RB…

人胰岛素样生长因子-1 ELISA试剂盒IGF-1 (human), ELISA kit

高灵敏ELISA试剂盒&#xff0c;4小时内可得结果&#xff0c;最低可检测34.2 pg/ml的IGF-1 胰岛素样生长因子-1&#xff08;IGF-1&#xff09;是一种多肽激素&#xff0c;在结构上与胰岛素相似。它参与调节中枢和周围神经系统的神经元生长和发育。IGF-1是一种有效的神经元凋亡抑…

【Zookeeper】what is Zookeeper?

官网地址&#xff1a;https://zookeeper.apache.org/https://zookeeper.apache.org/ 以下来自官网的介绍 ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. A…

机试复习-3

前言&#xff1a;前面耽误太多时间&#xff0c;2月份是代码月&#xff0c;一定抓紧赶上&#xff0c;每天至少两道题 day1 2024.2.6 1.排序开启&#xff1a; 1.机试考试&#xff1a;排序应用考察 c的qsort c的sort 作用&#xff1a;对数组&#xff0c;vector排序&#…

c#读取csv文件中的某一列的数据

chat8 (chat779.com) 上面试GPT-3.5,很好的浏览网站&#xff0c;输入问题&#xff0c;可得到答案。 问题1&#xff1a;c#如何在csv中读取某一列数据 解答方案&#xff1a;在 C#中&#xff0c;你可以使用File.ReadAllLines来读取CSV中的所有行&#xff0c;然后逐行解析每一行…

flask+vue+python跨区通勤人员健康体检预约管理系统

跨区通勤人员健康管理系统设计的目的是为用户提供体检项目等功能。 与其它应用程序相比&#xff0c;跨区通勤人员健康的设计主要面向于跨区通勤人员&#xff0c;旨在为管理员和用户提供一个跨区通勤人员健康管理系统。用户可以通过系统及时查看体检预约等。 跨区通勤人员健康管…

Linux 分析指定JAVA服务进程所占内存CPU详情

1、获取服务进程PID [rootVM-32-26-centos ~]# service be3Service status Application is running as root (UID 0). This is considered insecure. Running [25383]2、获取进程占用详情 [rootVM-32-26-centos ~]# cat /proc/25383/status Name: java Umask: 0022 State: S…

Linux 文件比较工具

在Linux系统中&#xff0c;文件比较是一种常见的任务&#xff0c;用于比较两个文件之间的差异。文件比较可以帮助我们找出两个文件的不同之处&#xff0c;或者确定它们是否完全相同。在Linux中&#xff0c;有多种方法可以进行文件比较。 1. diff 在Linux中&#xff0c;diff命…

啤酒:精酿啤酒与冷盘的清新搭配

在夏日的傍晚&#xff0c;当太阳逐渐西沉&#xff0c;微风轻轻拂过&#xff0c;与亲朋好友围坐在一起&#xff0c;享受Fendi Club啤酒与冷盘的清新搭配&#xff0c;无疑是一种生活的享受。这两者的结合&#xff0c;不仅为味蕾带来了全新的体验&#xff0c;更为我们带来了片刻的…

24、数据结构/排序相关练习20240206

一、现有无序序列数组为{23,24,12,5,33,5,34,7}&#xff0c;请使用以下排序实现编程。 函数1&#xff1a;请使用冒泡排序实现升序排序 函数2&#xff1a;请使用简单选择排序实现升序排序 函数3&#xff1a;请使用快速排序实现升序排序 函数4&#xff1a;请使用插入排序实现…