L38.【LeetCode题解】四数之和(双指针思想) 从汇编角度分析报错原因
目录
1.题目
2.分析
去重的代码
错误代码
3.完整代码
提交结果
1.题目
四数之和
给你一个由
n个整数组成的数组nums,和一个目标值target。请你找出并返回满足下述全部条件且不重复的四元组[nums[a], nums[b], nums[c], nums[d]](若两个四元组元素一一对应,则认为两个四元组重复):
0 <= a, b, c, d < na、b、c和d互不相同nums[a] + nums[b] + nums[c] + nums[d] == target你可以按 任意顺序 返回答案 。
示例 1:
输入:nums = [1,0,-1,0,-2,2], target = 0 输出:[[-2,-1,1,2],[-2,0,0,2],[-1,0,0,1]]示例 2:
输入:nums = [2,2,2,2,2], target = 8 输出:[[2,2,2,2]]提示:
1 <= nums.length <= 200-10^9 <= nums[i] <= 10^9-10^9 <= target <= 10^9
2.分析
本题和L37.【LeetCode题解】三数之和(双指针思想)题非常像,解法也是类似的,将原暴力解法的四重循环(循环变量为i,j,k,l)的最里面的两重循环换成双指针(left和right)即可
但题目条件限制"不重复的四元组",因此需要做去重操作,这个实现的思路在L37.【LeetCode题解】三数之和(双指针思想)文章中讲过了
去重的代码
i,j,left和right都要跳过相同的元素,一定要注意i,j,left,right不能超过各自的循环范围
left++;
while (nums[left]==nums[left-1]&&left<right)left++;right--;
while (nums[right]==nums[right+1]&&left<right)right--;j++;
while (nums[j]==nums[j-1]&&j<=nums.size()-3)j++;i++;
while (nums[i]==nums[i-1]&&i<=nums.size()-4)i++;
错误代码
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {if (nums.size()<4)return {}; sort(nums.begin(),nums.end());vector<vector<int>> ret;for (int i=0;i<=nums.size()-4;){for (int j=i+1;j<=nums.size()-3;){int left=j+1;int right=nums.size()-1;while (left<right){int sum=nums[i]+nums[j]+nums[left]+nums[right];if (sum>target)right--;else if (sum<target)left++;else//sum==target{ret.push_back({nums[i],nums[j],nums[left],nums[right]});left++;while (nums[left]==nums[left-1]&&left<right)left++;right--;while (nums[right]==nums[right+1]&&left<right)right--;}}j++;while (nums[j]==nums[j-1]&&j<=nums.size()-3)j++;}i++;while (nums[i]==nums[i-1]&&i<=nums.size()-4)i++;}return ret;}
};
报错信息:

sum超出int的存储范围,因为,sum最大可为
如果将int改成long long写成long long sum=nums[i]+nums[j]+nums[left]+nums[right];仍然会出错

明明已经用long long来扩大存储范围了却仍然会出错,想要找到具体原因需要看底层汇编代码的实现,查看Leetcode在线测试使用的编译器:
在What-are-the-environments-for-the-programming-languages找到了信息:

由于Leetcode的编译器为clang,可手动在Linux平台上测试,
先安装clang:
sudo apt update
sudo apt install clang
编译以下代码:
//保存为test.cpp
int main()
{int i=1000000000;int j=1000000000;int left=1000000000;int right=1000000000;long long sum=i+j+left+right;return 0;
}
要看底层,需要看汇编代码,指令为:
clang -S test.cpp
汇编代码为:
.text.file "test.cpp".globl main # -- Begin function main.p2align 4, 0x90.type main,@function
main: # @main.cfi_startproc
# %bb.0:pushq %rbp.cfi_def_cfa_offset 16.cfi_offset %rbp, -16movq %rsp, %rbp.cfi_def_cfa_register %rbpxorl %eax, %eaxmovl $0, -4(%rbp)movl $1000000000, -8(%rbp) # imm = 0x3B9ACA00movl $1000000000, -12(%rbp) # imm = 0x3B9ACA00movl $1000000000, -16(%rbp) # imm = 0x3B9ACA00movl $1000000000, -20(%rbp) # imm = 0x3B9ACA00movl -8(%rbp), %ecxaddl -12(%rbp), %ecxaddl -16(%rbp), %ecxaddl -20(%rbp), %ecxmovslq %ecx, %rdxmovq %rdx, -32(%rbp)popq %rbp.cfi_def_cfa %rsp, 8retq
.Lfunc_end0:.size main, .Lfunc_end0-main.cfi_endproc# -- End function.ident "clang version 10.0.0-4ubuntu1 ".section ".note.GNU-stack","",@progbits.addrsig
只看重点部分:按照Intel汇编代码的风格来说,四个1000000000分别存到了[rbp-8],[rbp-12],[rbp-16],[rbp-20]的位置,之后使用3次addl指令,都做了相同的事,都是,而且都是由ecx寄存器来接收,ecx寄存器是4字节,由于int类型的最大值约为
,因此在相加时会超过int类型的最大值,导致溢出,最后的movslq,作用为以符号扩展传送方式,将参数从4字节扩展为8字节,4字节是int类型,8字节是long long类型,会发生类型转换
注:movslq全称moves a 32-bit quantity (longword) into a 64-bit register (quadword) with sign extension
因此可以理解为:long long sum=i+j+left+right;的i+j+left+right先按int类型相加,最后将结果的类型转换为long long
为了解决按int类型相加时产生的溢出,可以加两次:
long long sum=nums[i]+nums[j];
sum+=nums[left]+nums[right];
(原因:nums数组的元素不会超过,两个元素的和不会超过
,比int类型的最大值要小)
或者只加一次,强制类型转换:
long long sum=nums[i]+nums[j]+(long long)(nums[left]+nums[right]);
注意:不能使用unsigned long long,数组元素值可为负
3.完整代码
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {if (nums.size()<4)return {}; sort(nums.begin(),nums.end());vector<vector<int>> ret;for (int i=0;i<=nums.size()-4;){for (int j=i+1;j<=nums.size()-3;){int left=j+1;int right=nums.size()-1;while (left<right){long long sum=nums[i]+nums[j];sum+=nums[left]+nums[right];if (sum>target)right--;else if (sum<target)left++;else//sum==target{ret.push_back({nums[i],nums[j],nums[left],nums[right]});left++;while (nums[left]==nums[left-1]&&left<right)left++;right--;while (nums[right]==nums[right+1]&&left<right)right--;}}j++;while (nums[j]==nums[j-1]&&j<=nums.size()-3)j++;}i++;while (nums[i]==nums[i-1]&&i<=nums.size()-4)i++;}return ret;}
};
提交结果

相关文章:
L38.【LeetCode题解】四数之和(双指针思想) 从汇编角度分析报错原因
目录 1.题目 2.分析 去重的代码 错误代码 3.完整代码 提交结果 1.题目 四数之和 给你一个由 n 个整数组成的数组 nums ,和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] (若两个四元…...
字符串系列一>最长回文子串
目录 题目:解析:代码: 题目: 链接: link 解析: 代码: class Solution {public String longestPalindrome(String s) {char[] ss s.toCharArray();int n ss.length;int begin 0;//返回结果的起始字符串…...
双击热备方案及不同方案的需求、方案对比
双击热备方案概述 一般实现双机热备的方案有三种,分别是共享存储双机热备方案、镜像双机热备方案、双机双柜双机热备方案,这三种方案对硬件要求不同,大家可以根据自身的业务应用特性来选择具体的双机热备方案以及对应的ServHA双机热备软件产品。 1、镜像双机热备 1.1镜像…...
Antd中使用Form.List且有Select组件,过滤问题
当在使用Form.List组件,且组件中有Select选项时,针对每一次选择,都要过滤掉那些已经选择过的选项,可能遇到的问题: 直接过滤会将每一个Select中的options选项都过滤掉,无法正常展示选择的选项 解决办法&a…...
VSCODE插值表达式失效问题
GET https://cdn.jsdelivr.net/npm/vue2.6.14/dist/vue.js net::ERR_CONNECTION_-CSDN博客 更换正确的vue域名 GET https://cdn.jsdelivr.net/npm/vue2.6.14/dist/vue.js net::ERR_CONNECTION_ <script src"https://unpkg.com/vue2.6.14/dist/vue.js"></sc…...
【失败】Gnome将默认终端设置为 Kitty
起因 一会儿gnome-terminal一会儿kitty终端,实在是受不了,决定取缔默认的gnome-terminal。 过程 在 Ubuntu 或 Debian 系统上: 确保 Kitty 已经安装。如果未安装,可以在终端中运行命令sudo apt install kitty -y进行安装。 使用系…...
蓝桥杯:连连看
本题大意要我们在一个给定的nxm的矩形数组中找出符合条件的格子 条件如下: 1.数值相同 2.两个横坐标和纵坐标的差值相等(由此可得是一个对角线上的格子) 那么根据以上条件我们可以用HashMap来解决这个问题,统计对角线上数值相同…...
Ext系列⽂件系统
Ext系列⽂件系统 1. 理解硬件1.1 磁盘的物理结构1.2 磁盘的存储结构1.3 磁盘的逻辑结构理解过程实际过程 1.4 CHS&&LBA地址 2. 引入文件系统块分区innode 3. Ext2文件系统3.1 宏观认识3.2 block group3.3 块组内部3.3.1 GDT(Group Descriptor Table…...
JavaScript 对象复制:浅拷贝与深拷贝
JavaScript 对象复制:浅拷贝与深拷贝使用说明 在 JavaScript 中,对象复制分为 浅拷贝 和 深拷贝,两者的核心区别在于是否递归复制嵌套的引用类型属性。以下是详细说明和示例: 一、浅拷贝(Shallow Copy) 特…...
MTK-Android12 13 屏蔽掉Viewing full screen
去掉ROOM 开机第一次提示全屏弹框 文章目录 需求参考资料修改文件实现方案 解决思路grep 源码查找信息grep 查找 grep -rn "Viewing full screen" 找string 字段grep 查找 grep -rn immersive_cling_title 布局grep 查找 grep -rn layout.immersive_mode_cling 对应的…...
mysql数据库的线程连接数、状态 、最大并发数、缓存等参数配置
mysql数据库的线程连接数、状态 、最大并发数、缓存等参数配置 https://www.modb.pro/db/1784385883449397248 mysql数据库的线程连接数、状态 、最大并发数、缓存等参数配置 SQL命令行临时设置操作 #查看mysql数据库的线程连接数: mysql> show global statu…...
OpenGauss 数据库介绍
OpenGauss 数据库介绍 OpenGauss 是华为基于 PostgreSQL 开发的企业级开源关系型数据库,现已成为开放原子开源基金会的项目。以下是 OpenGauss 的详细介绍: 一 核心特性 1.1 架构设计亮点 特性说明优势多核并行NUMA感知架构充分利用现代CPU多核性能行…...
GitHub创建远程仓库
使用GitHub创建远程仓库:从零开始实现代码托管与协作 前言 在当今软件开发领域,版本控制系统已成为开发者必备的核心工具。作为分布式版本控制系统的代表,Git凭借其强大的分支管理和高效的协作能力,已成为行业标准。而GitHub作为…...
【AI部署】腾讯云GPU -—SadTalker的AI数字人访问web服务—未来之窗超算中心
访问部署在Cloud Studio上的web服务 当你把该项目部署在本地时,访问该服务的请求地址为http://localhost:8080/hello;当你把该项目部署在Cloud Studio工作台启动时,要想访问到该服务,需要先在工作台右侧打开访问链接面板ÿ…...
基于spring boot 集成 deepseek 流式输出 的vue3使用指南
本文使用deepseek API接口流式输出的文章。 环境要求 jdk17 spring boot 3.4 代码如下: package com.example.controller;import jakarta.annotation.PostConstruct; import org.springframework.ai.chat.messages.AssistantMessage; import org.springframework.ai.chat.mes…...
fastdds:传输层SHM和DATA-SHARING的区别
下图是fastdds官方的图,清晰地展示了dds支持的传输层: 根据通信双方的相对位置(跨机器、同机器跨进程、同进程)的不同选择合适的传输层,是通信中间件必须要考虑的事情。 跨机器:udp、tcp 跨机器通信,只能通过网络, f…...
堆栈溢出 StackOverflowError 排查
报错: exHandler dispatch failed; nested exception is java.lang.StackOverflowError org.springframework.web.util.NestedServletException: Handler dispatch failed; nested exception is java.lang.StackOverflowError at org.springframework.web.servlet.D…...
树莓派_利用Ubuntu搭建gitlab
树莓派_利用Ubuntu搭建gitlab 一、给树莓派3A搭建基本系统 1、下载系统镜像 https://cdimage.ubuntu.com/ubuntu/releases/18.04/release/ 2、准备系统SD卡 二、给树莓派设备联网 1、串口后台登录 使用串口登录后台是最便捷的,因为前期网络可能不好直接成功 默…...
ARINC818协议(三)
源特定参数 源特定参数被定义,用于在源和目的之间进行传输 源特定参数包括初始化,合适的解释,周期性的验证。 gamma or palette tables:伽马或者调色板 color format:颜色格式 Brightness and backlight control :亮度…...
得佳胜哲讯科技 SAP项目启动会:胶带智造新起点 数字转型新征程
在全球制造业加速向数字化、智能化转型的浪潮中,胶带制造行业正迎来以“自动化生产、数据化运营、智能化决策”为核心的新变革。工业互联网、大数据分析与智能装备的深度融合,正推动胶带制造从传统生产模式向“柔性化生产精准质量控制全链路追溯”的智慧…...
万字解析TCP
通过学习视频加博客的组合形式,整理了一些关于TCP协议的知识。 *图源:临界~的csdn博客。 一、TCP建立连接 TCP的建立连接,大致可以分为面向连接、TCP报文结构、TCP的三次握手、TCP的建立状态、SYN泛洪攻击。 1.1、面向连接 面向连接 --- …...
PyTorch 浮点数精度全景:从 float16/bfloat16 到 float64 及混合精度实战
PyTorch 在深度学习中提供了多种 IEEE 754 二进制浮点格式的支持,包括半精度(float16)、Brain‑float(bfloat16)、单精度(float32)和双精度(float64),并通过统…...
2025年大数据实训室建设及大数据实训平台解决方案
一、引言 在数字化浪潮中,大数据技术已成为推动各行业创新发展的核心驱动力。从金融领域的风险预测到医疗行业的精准诊断,从电商平台的个性化推荐到交通系统的智能调度,大数据的应用无处不在。据权威机构预测,到 2025 年…...
我的机器学习之路(初稿)
文章目录 一、机器学习定义二、核心三要素三、算法类型详解1. 监督学习(带标签数据)2. 无监督学习(无标签数据)3. 强化学习(决策优化)(我之后主攻的方向) 四、典型应用场景五、学习路线图六、常见误区警示七…...
Python 高阶函数:日志的高级用法
日志装饰器的 **7 个高阶优化方案**,结合了生产环境最佳实践和调试深度需求: --- ### 一、**智能动态采样装饰器** 解决高频函数日志过多问题,自动根据错误率调整日志频率 python from collections import defaultdict import time cla…...
贪心、动态规划、其它算法基本原理和步骤
目录 1. 贪心1.1 贪心算法的基本步骤1.2 贪心算法实战1.2.1 贪心的经典问题1.2.2 贪心解决数组与子序列问题1.2.3 贪心解决区间调度问题1.2.4 贪心解决动态决策问题1.2.5 贪心解决一些复杂场景应用 2. 动态规划2.1 动态规划的基本步骤和一些优化2.2 动态规划实战2.2.1 斐波那契…...
python-各种文件(txt,xls,csv,sql,二进制文件)读写操作、文件类型转换、数据分析代码讲解
1.文件txt读写标准用法 1.1写入文件 要读取文件,首先得使用 open() 函数打开文件。 file open(file_path, moder, encodingNone) file_path:文件的路径,可以是绝对路径或者相对路径。mode:文件打开模式,r 代表以…...
[250418] 智谱 AI 发布新一代模型,同时推出新域名 Z.ai
目录 智谱开源 GLM-4-32B-0414 系列 AI 模型开源赋能,加速 AI 应用落地性能卓越,比肩顶尖模型应用广泛,赋能各行各业 智谱开源 GLM-4-32B-0414 系列 AI 模型 国内人工智能领军企业智谱华章正式开源新一代 GLM-4-32B-0414 系列大语言模型&…...
ctfshow-大赛原题-web702
因为该题没有理解到位,导致看wp也一直出错,特此反思一下。 参考yu22x师傅的文章 :CTFSHOW大赛原题篇(web696-web710)_ctfshow 大赛原题-CSDN博客 首先拿到题目: // www.zip 下载源码 我们的思路就是包含一个css文件,…...
Triton(2)——Triton源码接结构
1 triton 3.0.0 源码结构 triton docs/:项目文档 cmake/:构建配置相关 bin/:工具、脚本 CmakeLists.txt:cmake 配置文件 LSCENSE README.md Pyproject.toml:python 项目配置文件 utils/:项目配置文…...
