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

难度参考

        难度:中等

        分类:数组

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

题目

        给定一个包含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.hqwc.cn/news/455037.html

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

相关文章

推动海外云手机发展的几个因素

随着科技的不断发展&#xff0c;海外云手机作为一种新兴技术&#xff0c;在未来呈现出令人瞩目的发展趋势。本文将在用户需求、技术创新和全球市场前景等方面&#xff0c;探讨海外云手机在未来的发展。 1. 用户需求的引领&#xff1a; 随着人们对移动性和便捷性的需求不断增长&…

【FPGA】快速学习路径

FPGA学习教程、功利式学习路径、以找工作为目的&#xff0c;早日入门FPGA_哔哩哔哩_bilibili

统计数字出现次数的数位动态规划解法-数位统计DP

在处理数字问题时,我们经常遇到需要统计一定范围内各个数字出现次数的情况。这类问题虽然看起来简单,但当数字范围较大时,直接遍历统计的方法就变得不再高效。本文将介绍一种利用数位动态规划(DP)的方法来解决这一问题,具体来说,是统计两个整数a和b之间(包含a和b)所有…

2024/2/5总结

微信小程序 监听对象中所有属性的变化 如果某个对象中需要被监听的属性太多&#xff0c;为了方便&#xff0c;可以使用 通配符 ** 来监听 对象中所有属性的变化 什么是纯数字字段 概念&#xff1a;纯数字字段指的是那些不用于界面渲染的 data 字段。 好处&#xff1a;提升界面…

AI专题:海外科技巨头指引,AI主线逻辑依旧坚挺

今天分享的是AI 系列深度研究报告&#xff1a;《AI专题&#xff1a;海外科技巨头指引&#xff0c;AI主线逻辑依旧坚挺》。 &#xff08;报告出品方&#xff1a;华西证券&#xff09; 报告共计&#xff1a;54页 本周热点:海外科技巨头指引&#xff0c;AI主线逻辑依旧坚挺 硬件…

为什么(如何)从 Java 8/11 迁移到 Java 21,从 Spring Boot 2 迁移到最新的 Spring Boot 3.2 ?

介绍 如果您的工作配置与 Java 有一定的关系&#xff0c;您一定已经注意到 了Java 最新稳定版本 Java 21 引起了很多关注。 这个新版本引入了一些未来的功能&#xff0c;改进了之前引入/孵化的一些突破性功能&#xff0c;弃用了多余的功能&#xff0c;并删除了一些错误。它使…

【JavaEE Spring 项目】博客系统

博客系统 前⾔项⽬介绍1. 准备⼯作1.1 数据准备1.2 创建项⽬1.3 准备前端⻚⾯1.4 配置配置⽂件1.5 测试 2. 项⽬公共模块2.1 实体类的编写2.2 公共层 3. 业务代码3.1 持久层3.2 实现博客列表3.3 实现博客详情3.4 实现登陆令牌技术JWT令牌介绍JWT令牌⽣成和校验 3.5 实现强制要求…

CISCRISC? CPU架构有哪些? x86 ARM?

编者按&#xff1a;鉴于笔者水平有限&#xff0c;文中难免有不当之处&#xff0c;还请各位读者海涵。 是为序 我猜&#xff0c;常年混迹CSDN的同学应该不会没听说过CPU吧&#xff1f; 但你真的了解CPU吗&#xff1f;那笔者问你CPU有哪些架构呢&#xff1f; 如果你对你的答案…

从Kafka系统中读取消息数据——消费

从Kafka系统中读取消息数据——消费 消费 Kafka 集群中的主题消息检查消费者是不是单线程主题如何自动获取分区和手动分配分区subscribe实现订阅&#xff08;自动获取分区&#xff09;assign&#xff08;手动分配分区&#xff09; 反序列化主题消息反序列化一个类.演示 Kafka 自…

C++学习Day03之new和delete使用

目录 一、程序及输出1.1 new 和delete基础使用1.2 利用void*无法调用析构函数1.3 利用new开辟数组1.3.1 堆区开辟数组1.3.2 栈上开辟数组 二、分析与总结 一、程序及输出 1.1 new 和delete基础使用 malloc 和 new 区别 malloc 和 free 属于 库函数   new 和delete属于 运算符…

MySQL篇----第七篇

系列文章目录 文章目录 系列文章目录前言一、水平分区二、分库分表之后,id 主键如何处理三、存储过程(特定功能的 SQL 语句集)前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你…

SpringBoot-基础篇03

之前搭建了整个开发环境实现了登录注册&#xff0c;springBoot整合mybatis完成增删改查&#xff0c;今天完成分页查询&#xff0c;使用阿里云oss存储照片等资源&#xff0c;后期会尝试自己搭建分布式文件系统来实现。 一&#xff0c;SpringBootMybatis完成分页查询 1&#xff…