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

C++刷题——数组 文章目录1、下面定义数组的语句正确的是?2、已知数组 a 定义为: int a[][3]={{1,2,3},{4}}; , 则 a[1][2] 的值为?3、已知数组定义为 int a[2][4]; ,下列对数组元素引用正确的为?4、下列程序段错误的是?5、下列说法正确的是?6、运行下列程序结果为?7、请编写程序实现:检查字符串 s 中是否包含字符串 t ,若包含,则返回并输出 t 在 s 中的开始位置(下标值) ,否则返回 -1 。8、编程实现任意输入 10 个数,然后按从小到大的顺序输出这 10 个数。 阅读详情

题目来源:. - 力扣(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的范围 

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

【C++养成计划】不聊学习只谈干货(Day1) 给小白定制的专属《C++21天养成计划》,让你以最快的速度掌握C++编程 阅读详情

相关推荐

基于继电器与三极管的自动水泵控制器DIY:从电路原理到PCB制作实战

继电器作为一种利用电磁原理实现电路通断控制的电气开关,其核心价值在于通过小电流信号控制大电流负载,实现强弱电之间的安全隔离。在自动化控制领域,继电器常与三极管等半导体器件配合,构成驱动电路,将微弱的传感器信号放大,从而可靠地控制电机、水泵等执行机构。这种组合技术广泛应用于工业控制、智能家居及各类电子DIY项目中,例如实现水箱水位的自动检测与控制。本文将以一个典型的自动水泵控制器项目为例,深入剖析如何利用继电器与三极管搭建水位检测与驱动电路,并详细讲解从电路设计、PCB自制(热转印法)到系统调试的完整工程实践

weixin_31774841的博客 347

C++ 语法基础课 习题4 —— 数组

数组

qq_42731062的博客 1854

合成孔径雷达(SAR)的常见工作模式

随着星载SAR技术研究的深入发展,单一的条带模式已经无法满足当今时代的需求,因此许多新的工作模式相继被提出。这些新模式在分辨率和测绘宽度等方面都有所提高,接下来将简要介绍几种常用的工作模式。

m0_51390495的博客 2315

C++数组练习题(一)

我是计算机专业的一位大一本科生,C++小白,下面是我们学校在学习C++时用的基础练习题,我感觉这些题比较适合初学C++的码友,所以利用空闲时间将这些题整理出来,一是为了让初学C++的码友有所参考,二也是为了复习一下所学过知识。(因准备急促,如有代码错误,还请各位码友指正。) 1.逆序输出 从键盘输入n个整数(n<100),存放在一个一维数组中,逆序输出能被3整除 的元素,并逆序输出数组下标为3的倍数的元素。 输入格式:第一个整数为个数n,后续为n个整数 输出格式:第一行能被3整除的元素,第二行为下标为

Lucky_追梦仔的博客 2万+

STM32超声波避障小车硬件设计与实时测距实现

超声波测距是嵌入式系统中经典的环境感知技术,其原理基于声波在空气中的传播时间与距离的线性关系,通过精确计时实现非接触式距离测量。该技术具备成本低、抗光干扰强、算法简洁等优势,广泛应用于智能小车、机器人避障、液位监测等场景。工程落地的关键在于硬件信号完整性(如5V/3.3V电平匹配)、微秒级定时精度(依赖高稳定外部晶振与输入捕获模式)以及强干扰环境下的数据鲁棒性(需软硬协同滤波)。本文以STM32F103C8T6为平台,深入解析HC-SR04模块的时序闭环控制、TIM3输入捕获双沿测量、L298N电机状态机驱

weixin_42578963的博客 296

通达信短周期指标盘中实时监控与预警选股实战

本文详细介绍了通达信短周期指标在盘中实时监控与预警选股中的实战应用。通过分时指标改造、多股同列监控技巧及预警策略优化,帮助短线交易者捕捉转瞬即逝的交易机会,提升选股效率与准确性。重点解析了如何避免假信号干扰及系统卡顿问题,并探讨了从预警到自动交易的进阶应用。

weixin_29230805的博客 909

C++数组(简单练习)

C++数组基础练习

m0_65334471的博客 2763

从零抓包分析AVDTP:用Wireshark解密蓝牙音频传输全流程

本文详细介绍了如何使用Wireshark抓包工具分析AVDTP协议,解密蓝牙音频传输的全流程。从实验环境搭建到信令交互解析,再到媒体流传输深度分析,逐步揭示蓝牙音频传输的技术本质,帮助开发者深入理解AVDTP协议的工作机制。

sun99的博客 204

【算法】C++算法题总结-数组

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值 target,返回 [-1, -1]。示例 1:输入:nums = [5,7,7,8,8,10], target = 8输出:[3,4]示例 2:输入:nums = [5,7,7,8,8,10], target = 6输出:[-1,-1]示例 3:输入:nums = [], target = 0输出:[-1,-1]题解。

zq563100792的博客 1538

zabbix系列:内存VM.MEMORY.SIZE监控之total、free、pused、available 参数说明

free -m buffer是即将要被写入磁盘的,而cache是被从磁盘中读出来的. zabbix Web total:1046/1024=1.02G Available:216/1046=20.65% zabbix参数 total- 总物理内存. free- 可用内存. active- 内存当前使用或最近使用,所以它在RAM中。 inactive- 未使用内存. wired- 被标记为始终驻留在RAM中的内...

NIO4444 5668

科研级YOLOv8 Neck革新:BiFPN双向特征金字塔赋能,让多尺度融合更高效的实战指南

在文件夹下新建BiFPN.py,将上述BiFPNLayer和BiFPN类的代码写入其中。这一步是为了让YOLOv8的代码架构能识别我们的自定义Neck模块。

m0_64661770的博客 153

代码随想录|算法训练营Day7|454. 四数相加II,383. 赎金信 ,15. 三数之和 ,18. 四数之和

今天是day7,依然是哈希表,上几道比较有难度的核心算法题练习。

weixin_43978140的博客 1713

Pytorch CIFAR10图像分类 EfficientNet v1篇

EfficientNet源自Google Brain的论文EfficientNet: Rethinking Model Scaling for Convolutional Neural Networks. 从标题也可以看出,这篇论文最主要的创新点是. 论文提出了,混合缩放,把网络缩放的三种方式:深度、宽度、分辨率,组合起来按照一定规则缩放,从而提高网络的效果。EfficientNet在网络变大时效果提升明显,把精度上限进一步提升,成为了当前最强网络。

风信子的猫Redamancy的快乐星球 1852

C++day14(练习题)

【描述】请循环输出1~100之间的每个整数,输出时每行输出1个数,比如,输出结果的前10个数是这样的:【输入描述】无【输出描述】按要求输出1~100之间的每个数。【样例输入】无【样例输出】

weixin_46669997的博客 706

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

C++day017(练习题)

输出一个整数序列中与指定数字相同的数的个数输入包含2行:第1行为N和m,表示整数序列的长度(N≤100)和指定的数字, 中间用一个空格分开;第2行为N个整数,整数之间以一个空格分开。

weixin_46669997的博客 57

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C++入门Day0:规划开启

首先介绍一下自己本人初二生一枚,曾经有过编程基础( Python ),也曾几次学习 C++ ,但总是半途而废(悲),想要参加算法竞赛,所以开启计划,在180天看完,故制定了此计划。因为学业紧张(山东),每天实际能拿出来的时间仅有一小时,所以放慢进度,争取吃透本书。

linmohan0814的博客 1341

Day15Day16Day17Day18Day19Day20Day21

43.最高频率 题目:在游戏中,明明的爸爸要求明明在一串数字中,找出出现次数最多的那个数字,如果有多个数字出现的次数一样,则取最小的那个数字。明明很快就理解的游戏的规则,开始玩起来。明明的爸爸首先给了明明三个数字:3、2、1;明明很快就回答说:“1”(虽然3、2都出现一次,但是1是最小的数字,因此答案是1)。明明的爸爸很惊讶于明明的反应速度,开始加大游戏的难度,给出了由6个数字组成的数字串:2、1、3、4、5、2;明明眼珠子一转,脱口而出:“2”。明明的爸爸意识到简单的数字串很难难住明明,于是决定给出很长的

2201_75886338的博客 806

代码随想录Day12-哈希表&字符串:力扣第15、18、344题

21点才开始刷,结果整到了23点,溜了溜了。

Jerome_zp的博客 211

视频教程-《信息学竞赛-C/C++入门》 C++语言-C/C++

《信息学竞赛-C/C++入门》 C++语言 毕业于清华大学,曾担任Googl...

weixin_27035465的博客 1841

[学习笔记-C++篇]day17-18 牛客C++面经page1

只能说越学越觉得自己还需要学很多。 前10天打基础,4天入门基本题,现在要把算法入门一下。 有太多的所谓的学习计划了,连参考都不知道参考什么。 slow down。 从算法入门为切入,对某种算法专项训练。预计11天,到月底结束。下个月开始剑指offer。 链接:算法入门 c++校招面试题目合集 目录1.面试题第1页1.11.21.31.41.51.61.71.8小总结1.91.101.111.121.131.141.151.161.171.181.191.202.算法入门2.1 查找 1.面试题第1页 1

warningm_dm的博客 1610

C++ Primer Plus 第六版 编程练习题及详细答案

C++编程练习摘要 本文档包含了一系列C++编程练习的解决方案,涵盖了基础语法、函数、类、模板等核心概念。练习分为多个章节,每章包含若干题目。 主要内容 基础练习:变量声明、输入输出、简单计算等基础语法练习 函数与结构:函数定义、参数传递、结构体使用 面向对象:类定义、继承、多态、运算符重载 模板与STL:模板函数、模板类、标准模板库应用 文件I/O:文件读写操作 异常处理:异常类设计与使用 典型示例 简单I/O:显示姓名地址、单位换算 函数应用:温度转换、字符串处理 类设计:复数类、链表类、银行模拟类 S

misterxize的博客 394

day18【LeetCode力扣】19.删除链表的倒数第N个结点

fast先走n+1步,这样同时移动的时候slow指向删除节点的上一个节点。看完题述后,链表只能从前往后查找,根据这个特点,想到使用。给你一个链表,删除链表的倒数第。个结点,并且返回链表的头结点。

canGfly的博客 647

day13(练习题)

【描述】数学上把2的K次方叫2的K次幂,如4、8、32等。给定一个整数n,请输出距离它最近的那个2的幂是多少。如果有两个距离相同,输出那个小的。【输入描述】只有一个整数 n(10 <= n <= 2000000000)【输出描述】只有一个整数,表示距离 最近的那个2的幂。【样例输入】17【样例输出】16。

weixin_46669997的博客 625

【C++】黑马程序员《C++从入门到精通》

黑马程序员《C++从入门到精通》--学习笔记第八部分:bug与思考01、iostream和iostream.h和stdio.h的区别02、#define和const的区别03、using names std 什么意思?04、数据类型的意义?第一部分:基础入门知识(1-71)01、课程安排02、C++书写helloworld03、程序的注释04、变量05、常量06、关键字07、标识符命名规则08、数据类型第二部分:通讯录管理系统(01-12)0102第三部分:C++进阶知识(01-64)0102第四部分:职工

浪里小飞侠的博客 2万+

leetcode刷题记录day011:19和18

19、难度中等: 要求:使用一趟扫描实现 提示: 链表中结点的数目为 sz 1 <= sz <= 30 0 <= Node.val <= 100 1 <= n <= sz 方法一:原创题解:结构体数组 /** * 题目给出的该链表结构体构造: * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListN

CodeYello的博客 187

并非从0开始的c++ day7

1int age;} myPerson;//这里的是别名 void test01() {2//第二种定义方式 struct Person2 {int age;//myPerson2是结构体变量 void test02() {3//第三种定义 struct {int age;//匿名的 结构体变量 void test03() {

mcyuuji的博客 135
上一篇: C++算法练习-day18——15.三数之和
下一篇: C++算法练习-day20——344.反转字符串
Neophyte0608
博客等级 码龄3年 808粉丝 98原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Neophyte0608

你的鼓励将使我创作学的更加快乐

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值