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

news2024/11/15 20:01:22

难度参考

        难度:中等

        分类:数组

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

题目

        给定一个包含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;  // 右指针初始化

            // 使用双指针在剩余数组中寻找合适的两个数字,使得这四个数字之和为target
            while (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.coloradmin.cn/o/1436700.html

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

相关文章

【算法与数据结构】718、1143、1035、392、115、LeetCode最长重复子数组+最长公共子序列+不相交的线+判断子序列+不同的子序列

文章目录 一、718、最长重复子数组二、1143、最长公共子序列三、1035、不相交的线四、392、判断子序列五、115、不同的子序列六、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、718、最长重复子数组 思路分析&#xff1…

vue3-内置组件-TransitionGroup

<TransitionGroup> 是一个内置组件&#xff0c;用于对 v-for 列表中的元素或组件的插入、移除和顺序改变添加动画效果。 与 <Transition> 的区别 <TransitionGroup> 支持和 <Transition> 基本相同的 props、CSS 过渡 class 和 JavaScript 钩子监听器&…

Linux联网安装MySQL Server

yum安装 以下代码复制粘贴到控制台即可 yum list | grep mysql-server #查看可以下载的MySQLyum install -y mysql-server #安装MySQLmysql_secure_installation #引导安装 引导安装实例如下 systemctl enable mysqld 设置开机自动启动 systemctl sta…

重生奇迹MU冰风谷雪人王

奇迹雪人王刷怪点在哪里 冰风谷&#xff1a;就一个刷怪点&#xff0c;这里还是比较适合走动打怪&#xff0c;这里刷新4只雪人王&#xff0c;这里从100来级挂到200级问题不大。一般来说冰风谷的雪人王以及雪人王以上的怪都有一定几率会掉宝石,去血色、广场还有寺院掉的要多,不固…

XxlJob深度性能优化实践

一、背景 天画项目的数据工厂目前在与xxl-job对接自动化数据生成任务,另外我司也在使用该组件做业务,所以想深入了解下XxlJob。在跟进了社区的github等仓库issue发现开发迭代停滞了一段时间,思来想去准备开个下游分支做一些性能优化和特性开发等,于是fork了下源码,将其作…

环境配置:ROS melodic安装turtlebot

文章目录 1.已有的环境2.安装2.1.首先cd进入到catkin_ws文件夹&#xff0c;然后输入以下命令行&#xff1a;2.2.将turtlebot加入环境2.3.选择性安装其它依赖包2.4.运行turtlebot in stage [perfect] 1.已有的环境 在之前已经配置好了小乌龟的前提下&#xff0c;我们已经拥有了…

2024/2/4 备战蓝桥杯 5-1 前缀和

目录 求和 0求和 - 蓝桥云课 (lanqiao.cn) 可获得的最小取值 0可获得的最小取值 - 蓝桥云课 (lanqiao.cn) 领地选择 P2004 领地选择 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 求和 0求和 - 蓝桥云课 (lanqiao.cn) 思路&#xff1a;先对公式进行合并同类相&#x…

AVR 328pb触摸功能基本介绍和使用

AVR 328pb触摸功能基本介绍和使用 &#x1f4dd;ATMEGA328PB-AU外设中带外围触摸控制器&#xff08;PTC&#xff09;电容式触摸按钮、滑块和轮子24个自帽通道和144个互帽通道。&#xff08;ATMEGA328P没有的&#xff09; ✅PTC-外围触摸控制器 &#x1f343;低功耗、高灵敏度、…

图形界面基础

X Window System 什么是 X Window System&#xff1f; 最初是1984年麻省理工学院的研究&#xff0c;之后变成UNIX、类UNIX、以及OpenVMS等操作系统所一致适用的标准化软体工具套件及显示架构的运作协定。X Window系统透过软体工具及架构协定来建立操作系统所用的图形用户界面&a…

Flink SQL Client 安装各类 Connector、Format 组件的方法汇总(持续更新中....)

博主历时三年精心创作的《大数据平台架构与原型实现&#xff1a;数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行&#xff0c;点击《重磅推荐&#xff1a;建大数据平台太难了&#xff01;给我发个工程原型吧&#xff01;》了解图书详情&#xff0c;…

Redis-布隆过滤器解决穿透详解

本文已收录于专栏 《中间件合集》 目录 背景介绍概念说明原理说明解决穿透安装使用安装过程Redis为普通安装的配置方式Redis为Docker镜像安装的配置方式 具体使用控制台操作命令说明Spring Boot集成布隆过滤器 总结提升 背景介绍 布隆过滤器可以帮助我们解决Redis缓存雪崩的问题…

算法笔记刷题日记——3.简单入门模拟 3.2 查找元素

刷题日记 3.2 查找元素 B1041 B1004 B1028 B1032 A1011 A1006 A1036 错题记录 B1028 人口普查 某城镇进行人口普查&#xff0c;得到了全体居民的生日。现请你写个程序&#xff0c;找出镇上最年长和最年轻的人。 这里确保每个输入的日期都是合法的&#xff0c;但不一定是合理的…

Javascript入门学(基础)

软件篇 JS基础语法第一天 1.javascript介绍 1.1 js是什么 是什么 是一种运行在客户端&#xff08;浏览器&#xff09;的编程语言&#xff0c;实现人机交互效果&#xff0c;而html和css是标记性语言&#xff0c;并非编程语言有什么用 js的组成 htmlcssjs实现按钮点击功能 …

使用mmrotate对自定义数据集进行检测

这里写自定义目录标题 安装虚拟环境创建与准备安装mmrotate 自定义数据集标注数据与格式转换数据集划分与大图像切片 训练与测试修改配置文件执行训练进行测试鸣谢 安装 mmrotate是一个自带工作目录的python工具箱&#xff0c;个人觉得&#xff0c;在不熟悉的情况下&#xff0…

node.js后端+小程序前端+mongoDB(增删改查)

前言 今天我对比了以下node.js的express与python的fastAPI&#xff0c;我决定我还是出一期关于node.jsmangoDB小程序的小案例吧。 不是python的fastAPI不好用&#xff0c;因为fastAPI是python较新的技术&#xff0c;我不敢果断发出教学文章&#xff08;这件事情还是留着给pyt…

Leetcode—59. 螺旋矩阵 II【中等】

2024每日刷题&#xff08;113&#xff09; Leetcode—59. 螺旋矩阵 II 实现代码 class Solution { public:vector<vector<int>> generateMatrix(int n) {vector<vector<int>> ans(n, vector<int>(n));int num 0;int c1 0, c2 n - 1;int r1 …

探索C语言结构体:编程中的利器与艺术

✨✨ 欢迎大家来到贝蒂大讲堂✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;C语言学习 贝蒂的主页&#xff1a;Betty‘s blog 1. 常量与变量 1. 什么是结构体 在C语言中本身就自带了一些数据类型&#x…

Verilog刷题笔记21

题目&#xff1a; A priority encoder is a combinational circuit that, when given an input bit vector, outputs the position of the first 1 bit in the vector. For example, a 8-bit priority encoder given the input 8’b10010000 would output 3’d4, because bit[4…

假期算法提升(带你彻底掌握滑动窗口)

呀哈喽&#xff0c;我是结衣。 今天我们要学习的是一种新的算法&#xff0c;也是一种双指针。不过他拥有一个全新的名字”滑动窗口“。 文章目录 1.长度最小的子数组&#xff08;medium&#xff09;思路解题方法Code 2.无重复字符的最长子串&#xff08;medium&#xff09;思路…

【WebSocket】微信小程序原生组件使用SocketTask 调用星火认知大模型

直接上代码 微信开发者工具-调试器-终端-新建终端 进行依赖安装 npm install base-64 npm install crypto-js 然后顶部工具栏依次点击 工具-构建npm // index.js const defaultAvatarUrl https://mmbiz.qpic.cn/mmbiz/icTdbqWNOwNRna42FI242Lcia07jQodd2FJGIYQfG0LAJGFxM4FbnQ…