15.三数之和(双指针,C解答附详细分析)

题目描述:

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

注意:答案中不可以包含重复的三元组。

示例 1:

输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
解释:
nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。

示例 2:

输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

示例 3:

输入:nums = [0,0,0]
输出:[[0,0,0]]
解释:唯一可能的三元组和为 0 。

优秀解答:

int cmp(const void* pa, const void* pb){int a=*(int*)pa;int b=*(int*)pb;return a>b?1:-1;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){int base=100;//数组的初始长度,可更改//初始化处理返回值,二维数组的大小和保存每一个一维数组大小的数组的空间保持一致int** res=(int**)malloc(sizeof(int*)*base);*returnColumnSizes=(int*)malloc(sizeof(int)*base);*returnSize=0;int i,j,k;//排序qsort(nums,numsSize,sizeof(int),cmp);for(i=0;i<numsSize;i++){//先确定第三个数的值,再对剩下的两个数进行两数之和的操作//若本次的第三个数与上一次的情况相同,则跳过这个数if(i>0&&nums[i]==nums[i-1])continue;//给定nums[i],以j,k作为双指针进行两数之和操作j=i+1;k=numsSize-1;while(j<k){int sum=nums[i]+nums[j]+nums[k];if(sum==0){//刚好遇见符合要求的三元组//申请返回值二维数组的空间res[*returnSize]=(int*)malloc(sizeof(int)*3);//每一个数组大小都为3(*returnColumnSizes)[*returnSize]=3;//给申请的空间赋值res[*returnSize][0]=nums[i];res[*returnSize][1]=nums[j];res[*returnSize][2]=nums[k];//二维数组的行数加1(*returnSize)++;//如果二维数组的大小达到初始设定的行数,则进行空间扩容if(*returnSize==base){base*=2;res=(int**)realloc(res,sizeof(int*)*base);*returnColumnSizes=(int*)realloc(*returnColumnSizes,sizeof(int)*base);}//记录符合要求的两个数,进行去重int num1=nums[j],num2=nums[k];while(nums[j]==num1&&j<k)j++;while(nums[k]==num2&&j<k)k--;}//若三个数之和小于0,则左边的指针右移else if(sum<0)j++;//若三个数的之和大于0,则右边的指针往左移else k--;}}return res;
}

解答来自用户:烟火

分析:本题用C语言实在复杂,涉及到二维数组的空间分配,有很多细节需要注意。

1.区分指针,指针的值,指向指针的指针。

        本题中res是一个二维数组,为指向int指针的指针,可以理解为一个元素为int指针的一维数组。由于题解写在函数里,函数内部定义的变量都属局部变量,而return只能返回一个参数,所以用指针returnSize返回三元组的个数。

        用指向指针的指针returnColumnSizes返回每一行数组的长度。(非常绕,多想一想!)原作者给出的解释为“而在三数之和中,要求我们返回的其实是一个二维数组,那么我们除了需要知道二维数组的行数,每一行的数组的长度也是需要返回的,这就是另一个参数int** returnColSize 的用途,至于为什么这里也是一个指向指针的指针,因为returnColSize是我们从外部传进来的一个指针参数,要想保证在函数中对该指针的改变对外部产生影响,那么我们在外部传入的时候,也应该按照传引用的方式传入一个指针的地址,反映到函数中就是一个指向指针的指针。”

        returnSize作为一个int类型的指针,*returnSize为指针指向的值,即一个int值,可以用res[*returnSize]索引二维数组的行。还需要注意增加三元组个数时(*returnSize)++;的括号,如果不加括号则成了使指针值递增,而不是使指针指向的int元素递增。

        总结一下,res是一个指向指针的指针,指向存储答案的二维数组,其中每一个符合要求的三元组为一行;returnColumnSizes是一个指针,指向存储了每行大小(本题固定为3)的一维数组;returnSize是一个指针,指向三元组的个数,即二维数组的行数。

2.C语言中未知大小数组的空间分配。

        C语言中的数组分配必须要有固定大小,给解题增加了难度。本题作者定义了一个初始大小base进行空间分配,在每次循环中都要比较当前三元组个数是否超过了分配的大小,如果空间不够用增加base大小,调用realloc(res,sizeof(int*)*base);在原来的基础上增加分配空间。以此实现变长数组。malloc分配空间,realloc增加空间,calloc分配初始化为0的空间。

3.解题思路分析。

        先通过排序使数组有序,再依次遍历数组元素 i ,对于每个 i ,定义 j 初始指向剩余元素中的最小元素,定义 k 初始指向剩余元素中的最大元素,若三者和小于0,则将 j 右移,使得新的三数和更大,更有机会满足要求,否则 k 右移。这是双指针移动的一种基本思路,与题目11.盛水最多的容器相同, j 和 k 都不走回头路,使得二者移动的步数加起来为n,而若用暴力解的双层for循环则为n平方。故本题的解题思路可以理解为进行了n次11题的循环。

相关题目链接:11.盛水最多的容器(双指针,C解法)-CSDN博客

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

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

相关文章

暴力破解的基础知识和Burpsuite基础知识

定义 暴力破解 (Brute Force)也称为字典攻击&#xff0c;通常被用于攻击网站的用户账户名/密码 使用自动化脚本以枚举的方式尝试所有可能的用户名或密码组合。通过攻击用户的账户名和密码&#xff0c;窃取用户个人信息或获取网站管理权限等。 暴力破解攻击产生原因 1、用户口…

【mujoco】Ubuntu20.04中解决mujoco报错raise error.MujocoDependencyError

【mujoco】Ubuntu20.04中解决mujoco报错raise error.MujocoDependencyError 文章目录 【mujoco】Ubuntu20.04中解决mujoco报错raise error.MujocoDependencyError1. 报错的具体情况2. 解决过程3. 其他问题3.1 ModuleNotFoundError: No module named OpenGL3.2 ModuleNotFoundEr…

AUTOSAR汽车电子嵌入式编程精讲300篇-面向不平衡样本的车载网入侵检测系统 设计与实现 (续)

目录 3.2 传统CANTransfer模型原理 3.2.1 传统CANTransfer模型结构及特点 3.2.2 二维空间变换分析

nc的用法

nc的用法 测试udp端口是否可用 如果是测试某个IP地址地址是否可以访问&#xff0c;通常会使用 ping 命令&#xff0c;执行之后如果可以到达就会得到数据反馈&#xff1a; alberthome-pc:~$ ping 82.156.125.169 PING 82.156.125.169 (82.156.125.169) 56(84) bytes of data.…

第84讲:基于各种场景使用mysqldump逻辑备份数据库

文章目录 1.mysqldump备份工具的语法格式2.使用mysqldump进行全库备份3.备份单个库或者多个库的数据4.备份某个库下的单表或者多表的数据5.mysqldump备份数据库时必加的一些参数5.1.基本参数5.2.核心参数 6.mysqldump备份数据库时的一些其他参数 1.mysqldump备份工具的语法格式…

Docker Compose--部署SpringBoot项目--实战

原文网址&#xff1a;Docker Compose--部署SpringBoot项目--实战-CSDN博客 简介 本文用实战介绍Docker Compose部署SpringBoot项目。 1.创建SpringBoot项目 Controller package com.knife.example.controller;import io.swagger.annotations.Api; import io.swagger.annot…

HTTP基础知识总结

目录 一、什么是HTTP&#xff1f; 二、与HTTP有关的协议 三、HTTP请求特征 四、HTTP组成格式 五、HTTP标头 1.通用标头 2.实体标头 3.请求标头 4.响应标头 六、HTTP状态码分类 我们在日常测试过程中&#xff0c;也可以通过浏览器F12简单定位是前端问题还是后端问题&a…

Linux mrd命令教程:如何删除MS-DOS文件系统中的目录(附实例教程和注意事项)

Linux mrd命令介绍 mrd命令是用于删除MS-DOS文件系统中的目录。这是mtools工具指令&#xff0c;模拟MS-DOS的rd指令&#xff0c;可以删除MS-DOS的目录。 Linux mrd命令适用的Linux版本 mrd命令在所有主流的Linux发行版中都可以使用&#xff0c;包括但不限于Ubuntu&#xff0…

KeyError: ‘model_state_dict‘

问题 加载模型权重文件时获取model_state_dict键失败 解决 单步调试发现保存模型权重时正确保存了该键值对&#xff0c;再次调试时发现莫名奇妙又没错了 首先确认保存模型时的状态字典键名&#xff1a;确保在保存模型权重时&#xff0c;正确地使用了 model.state_dict() 方法…

局部与整体的关联特性,如图所示

局部与整体的关联特性是指事物的局部部分与整体之间存在一定的关联关系。它强调整体是由局部构成&#xff0c;局部又反向影响整体。具体包括以下几个方面的特性&#xff1a; 互依性&#xff1a;局部与整体相互依赖&#xff0c;一个的变动会影响另一个的变动。局部的变化会对整体…

Python-CSV文件的存储

CSV文件存储 CSV其文件以纯文本形式存储表格数据。CSV文件是一个字符序列&#xff0c;可以由任意数目的记录组成&#xff0c;各种记录由某种换行符分隔开。它比Excel文件更加简洁&#xff0c;XLS文本是电子表格&#xff0c;包含文本、数值、公式和格式等内容&#xff0c;CSV中则…

Linux系统使用超详细(六)~进程管理

目录 一、认识进程 二、进程号 2.1.进程号概念 2.2.进程号作用 三、进程查看 3.1. ps命令&#xff1a; 3.2. top命令&#xff1a; 3.3. htop命令&#xff1a; 3.4. pstree命令&#xff1a; 3.5. pgrep命令&#xff1a; 四、进程状态 五、进程优先级 六、进程优先…

neo4j图数据库安装和测试

neo4j图数据库安装和测试 1. 下载合适的neo4j软件版本。 https://we-yun.com/doc/neo4j/ https://neo4j.com/deployment-center/#enterprise 2. 下载JAVAJDK 由于neo4j是一个用Java编写的图形数据库&#xff0c;因此在安装和运行Neo4j之前&#xff0c;需要先安装Java Developm…

真机调试HarmonyOS应用报错

问题表现&#xff1a; 01/04 19:00:01: Launching com.example.simplevideo $ hdc shell am force-stop com.example.simplevideo $ hdc shell bm uninstall com.example.simplevideo $ hdc file send E:\harmony\SimpleVideo\entry\build\default\outputs\default\entry-defau…

docker (portainer 安装nginx)

汉化版步骤可以参考&#xff1a;写文章-CSDN创作中心https://mp.csdn.net/mp_blog/creation/editor/135258056 一、创建容器 二、配置端口&#xff0c;以及容器卷挂载 挂载目录配置&#xff1a;(下方截图的目录如下&#xff0c;docker 改为 mydocker&#xff0c;用docker作为根…

使用KVM命令集管理虚拟机

1、KVM基本功能管理 1&#xff09;查看命令帮助 [rootlocalhost ~]# virsh -h ......//省略输出内容 2&#xff09;查看KVM的配置文件存放目录&#xff08;rhel7.1是虚拟机系统实例的配置文件&#xff09; [rootlocalhost ~]# ls /etc/libvirt/qemu autostart networks r…

《设计模式》之策略模式

策略模式定义 比如对象的某个行为&#xff0c;在不同场景有不同实现方式&#xff0c;可以将这些行为的具体实现定义为一组策略&#xff0c;每个实现类实现种策略&#xff0c;在不同场景使用不同的实现&#xff0c;并且可以自由切换策略。 策略模式结构 策略模式需要一个策略…

react antd,echarts全景视图

1.公告滚动&#xff0c;40s更新一次 2.echarts图标 左右轮播 60s更新一次 3.table 表格 import { useState, useEffect } from react;import Slider from react-slick; import slick-carousel/slick/slick-theme.css; import slick-carousel/slick/slick.css;import Layout fro…

WiFi7: MLD寻址

原文:MLD使用MLD MAC address唯一的标识本MLD。 MLD下的STA(s)使用与之不同的MAC address。 NOTE MLD MAC address可以和其下的某个STA的MAC address相同或者不同于任一MAC Address。 原文:对于individually addressed 帧。以下规则适用: Address 2(TA)设置为STA的MAC Add…

springboot项目 java -jar xxx.jar 没有主清单属性解决方法

1.在pom文件中添加如下 <plugins><!--解决SpringBoot打包成jar后运行提示没有主清单属性--><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><configuration><fork…