C语言好题分享七(三数之和)

❀❀❀ 文章由@不准备秃的大伟原创 ❀❀❀

♪♪♪ 若有转载,请联系博主哦~ ♪♪♪

❤❤❤ 致力学好编程的宝藏博主,代码兴国!❤❤❤

   三数之和

  题目来源LeetCode:刷题传送门

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

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

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

c9c7464be3304d1abf8577f84d5aa562.png

  由题目可以得到我们呢需要求的是一个数组内的三个和为0的元素,且需要是不同的三个元素。

  其实当我们进去做题目的时候会发现提干处会有如下一段英文

/*

 * Return an array of arrays of size *returnSize.

 * The sizes of the arrays are returned as *returnColumnSizes array.

 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().

 */

简单翻译一下就是: 

返回一个大小为 *returnSize 的数组,数组中的每个元素都是一个数组。

  • 数组的大小作为 *returnColumnSizes 数组返回。

  • 注意:返回的数组和 *columnSizes 数组都必须使用 malloc 进行分配内存,假设调用者会调用 free() 进行释放。

         在C语言中我们不仅要实现代码,还需要考虑*returnSize和*returnColumnSize的开辟,这一点其实是在做题时C比其他语言要繁琐的地方

        算法一:暴力求解

  同样的我们先来最简单也最容易想到的暴力求解:使用三个for循环一个一个找:(伪代码实现)

//由于这段代码有很多的细节没有考虑,所以暂时就先不管returnSize和returnColumnSize的开辟了
int** ans = malloc(sizeof(int*)*numsSize)
for(int i = 0; i < numsSize - 2; i++){for(int j = i + 1; j < numsSize - 1; j++){for(int k = numsSize - 1; k > 1; k--){
ans[*returnSize][0] =nums[i];//ans为一个二维数组
ans[*returnSize][1] =nums[j];
ans[*returnSize][2] =nums[k];
(*returnSize++);
//如果满足ans[i] + ans[j] + ans[k] == 0 则存入ans里
}
}
}
return ans;

        这一种方法很笨,但是也很容易想到,时间复杂度是O(N*N*N)。

        那我们来想一想这一段代码除了没有考虑returnSize的returnColumnSize的开辟,其他有没有什么别的问题?

        是的,聪明且细心的铁汁一定发现了,题目要求:不同的三元组,所以我们还需要写一段代码判断是否有重复的答案存在。

        好的,到这里铁汁们是不是头都要秃了啊?○( ^皿^)っHiahiahia…  那这样,我们先来看一条类似的但更简单的题目:

        两数之和

  题目来源LeetCode:刷题传送门

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

5d495dbf2acc4c1c8a4e250248b60bf9.png 

/**

 * Note: The returned array must be malloced, assume caller calls free().

 */

 返回的答案必须使用 malloc 进行分配内存,假设调用者会调用 free() 进行释放。

  思想一:暴力求解

        太简单了,所以博主直接放代码了:

int* twoSum(int* nums, int numsSize, int target, int* returnSize)
{for(int i = 0; i < numsSize; i++){for(int j = i + 1; j < numsSize; j++){if(nums[i] + nums[j] == target){*returnSize = 2;int* ans = (int*)malloc(sizeof(int) * 2);ans[0] = i; ans[1] = j; return ans;}}} *returnSize = 0;return NULL;
}

  思想二:排序+双指针

  看过博主上一篇好题分享的铁汁们应该对双指针有所了解了,其实在熟练掌握了排序+双指针之后像这种类似的题目的第一个想法就应该是双指针了。

  两数之和比三数之和简单的原因不仅是数字变少了,而且最终的答案也只有一组解,不需要考虑去重,需要开辟的空间内容也少了。

        不知道铁汁们还记不记得上一次的双指针思路了,不记得的话....:--->盛水最多的容器

    好的,我们大概回顾一下哈~:我们所谓的双指针呢,不是真的指针,而是用两个数来表示数组的下标,一般一个指向第一个元素,一个指向最后一个元素,在不同的情况下对两个数进行不同的操作。 

        嗯...怎么说呢,这道题想到双指针本身是很好的想法,但是我们答案需要我们返回的是元素下标,所以如果我们使用qsort排序后,下标就会被打乱,这样返回的答案就会有错误。 那如果我们改一下,最后的答案求的是两个值,那么双指针就是嘎嘎棒了!

        虽然求两个数的和我们不可以用双指针,但是我们可以把思维套用到求三个数的和的那个题目上:

三数之和の思想二:排序+双指针

        首先我们先把nums排个序,因为我们的方法是以排序为起点的嘛:

 int cmp(const int* p1,const int* p2){return *p1 - *p2;}
//函数内
qsort(nums,numsSize,sizeof(int),cmp);

        首先我们先实现代码的主体:不管怎么说,实现题目的需求才是第一重要嘛:

int j = 0;//这里引用一个变量j,表示的答案有多少个,即returnSize,所以只要最后=一下就可以了 
int left = 0;int right = i - 1;while(left < right){if(nums[left] + nums[right] + nums[i] == 0) {ans[j] = (int*)malloc(sizeof(int) * 3);ans[j][0] = nums[left];ans[j][1] = nums[right];ans[j][2] = nums[i];j++;left++;right--;}else if(nums[left] + nums[right] + nums[i] > 0)right--;elseleft++;

        好,上面我们已经实现了主体,接下来我们需要考虑*reuturnSize和*returnColumnSize 内存的开辟:但是~先别急,我们在写答案的时候如果没有可以返回的答案能行吗? 当然不行了啊,所以呢,在考虑其他细节之前,我们要把答案存到一个二维数组里面啊!

    int** ans = malloc(sizeof(int*)*numsSize*numsSize);
//行ans[j][0] = nums[left];ans[j][1] = nums[right];ans[j][2] = nums[i];
//三列,在暴力求解里已经写过了

      这时候会有铁汁问了:“博主啊,你这个**ans为什么开辟了个numsSize*numsSize*sizeof(int) 大小的空间啊?” ,问得好,其实我们可以想象一下:

  三个数和为0,当其中一个数变化,其他一个或者两个数肯定会变化的,而我们考虑最坏的情况,每次三个数只动两个数就可以满足和为0,那这是不是就类似两个 变量的循环,复杂度为O(N*N),最后不也就是numsSize*numsSize*sizeof(int) ?

  但我们毕竟不能准确的计算需要的空间,开辟的大一点以防止越界。

   接下来我们考虑*reuturnSize和*returnColumnSize 内存的开辟:由函数主体可以得到j就是*returnSize,所以不知不觉中我们就把他的值给算出来了,而*returnColumnSize就比较麻烦了:

*returnColumnSizes = (int*)malloc(numsSize * numsSize *sizeof(int));
//行(同样的,开辟大一点没什么不好)
(*returnColumnSizes)[j] = 3;
//列(可以直接放在while循环内,每一行就是3个元素)
*returnSize = j;

  这时候我们的代码就基本写好了,然后会有铁汁迫不及待的点个提交,然后“啪”的一下显示个错误,然后又回来骂博主了:“你这教的啥,都错的!”        

  诶诶诶,别啥事都赖我啊o(TヘTo) , 还亏我在文章开头夸你呢!现在我又得骂你记性不好了!  (┬_┬)↘ 

  忘了吧?是不是忘了?忘了去重了吧?!

  其实实现去重也是比较简单的:

4cdb154705b542d5b6a606151ed44a07.png

  但是又有一个问题了:如果我们的案例是{0,0,0,0}的话不就会越界吗?所以我们还需要加个判断条件,代码实现如下:

while(left < right && nums[left] == nums[left + 1]) left++;while(right > left && nums[right] == nums[right - 1]) right--;
//千万记住left < right要放在==前面,因为&&的短路性质,当前面条件不成立的时候,就不会判断后面的条件,所以也就不会报错

   最后我们只需要return ans;就可以完成我们的代码了,展示一下自己的成果吧:

int cmp(const int* p1,const int* p2){return *p1 - *p2;}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){qsort(nums,numsSize,sizeof(int),cmp);int** ans = malloc(sizeof(int*)*numsSize*numsSize);*returnColumnSizes = (int*)malloc(numsSize * numsSize *sizeof(int));int j = 0;
for(int i = numsSize - 1; i > 1; i--)
{if(i < numsSize -1 && nums[i] == nums[i + 1]) continue;int left = 0;int right = i - 1;while(left < right){if(nums[left] + nums[right] + nums[i] == 0) {(*returnColumnSizes)[j] = 3;ans[j] = (int*)malloc(sizeof(int) * 3);ans[j][0] = nums[left];ans[j][1] = nums[right];ans[j][2] = nums[i];j++;while(left < right && nums[left] == nums[left + 1]) left++;while(right > left && nums[right] == nums[right - 1]) right--;left++;right--;}else if(nums[left] + nums[right] + nums[i] > 0)right--;elseleft++;}
}
*returnSize = j;
return ans;}

  然后提交,通过!b2468ef9694a48228dc5c904e2693dbf.png 

  这一路走下来真的很艰辛啊,但是无论什么道路都不会是轻松的,而且这也是我们成长的必经之路啊!但其实我们回过头来再仔细看看,想一想,这其实也没什么,当我们会这么觉得的时候,你已经成长了!

  由于再过几天全国各大高校都要举行四六级考试了,博主在这里祝各位学子(当然包括博自己了)四六级一举通过! 绩点刷满!期末永不挂科!

  那么本篇博客也就到此为止了,给大家送上个祝福,勉励自己以及这世界上所有追逐梦想的赤子趁年华尚好努力提升自己,莫欺少年穷!(看博主这么诚心诚意,给个赞不过分吧!ヾ(^▽^*))) )

22f93c7c787343e4a35d32ae8a9cc148.jpeg

 

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

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

相关文章

EasyRecovery2024专业版下载安装步骤图文详细教程

EasyRecovery是一款操作安全、价格便宜、用户自主操作的非破坏性的只读应用程序&#xff0c;它不会往源驱上写任何东西&#xff0c;也不会对源驱做任何改变。它支持从各种各样的存储介质恢复删除或者丢失的文件&#xff0c;其支持的媒体介质包括&#xff1a;硬盘驱动器、光驱、…

2-分布式存储之glusterfs

任务背景 实现了远程的存储共享(NAS或SAN)后, 公司业务发展迅速, 存储空间还需要增大。使用NAS或SAN都不方便扩容&#xff0c;NAS可以增加新的挂载目录, SAN可以增加新的硬盘&#xff0c;但我们希望直接在原来挂载的业务目录上实现在线扩容&#xff0c;数据体量越来越大, 这个…

ChatGLM3-6B和langchain知识库阿里云部署

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、ChatGLM3-6B部署搭建环境部署GLM3 二、Chatglm2-6blangchain部署本地知识库三、Tips四、总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&am…

被央视报道过的AIGC产品-贝塔创作(BetaCreator)使用指南

产品地址&#xff1a;betacreator.com 真人图 人台图 商品图 商品变色 建议使用浅色服装进行变色&#xff0c;效果更好 如果没有浅色服装&#xff0c;可以先把服装颜色变为白色

视频剪辑必备的6个免费素材网站

视频剪辑需要用到很多音效、视频、图片等素材&#xff0c;下面我就分享几个剪辑必备的免费视频素材网站&#xff0c;赶紧收藏起来~ 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 菜鸟图库虽然是个设计素材网站&#xff0c;但除了设计类素材之外还有很多视频、…

python学习:浅拷贝与深拷贝详解

copy 一、 & is二、浅拷贝 & 深拷贝(一)、浅拷贝(二)、深拷贝 三、问题 一、’ ’ & ‘is’ ’ 和is是python对象比较常用的两种方式,简单来说,‘ ‘操作符比较对象之间的值是否相等,如 a b 而’is’操作符比较的是对象的身份标识是否相等,即它们是否是同一个…

Linux系统解决“Key was rejected by service”

Linux系统下加载驱动模块出现如上错误提示的原因为&#xff1a;此驱动未经过签名。 方法一、关闭Secure Boot 如果是物理机&#xff0c;需要开机进入BIOS&#xff0c;找到“Secure Boot”的选项&#xff0c;然后关闭。 如果是虚拟机&#xff0c;可以打开虚拟设置&#xff0c…

快速准确翻译文件夹名:英文翻译成中文,文件夹批量重命名的技巧

在处理大量文件夹时&#xff0c;可能会遇到要将英文文件夹名翻译成中文的情况。同时也可能要批量重命名这些文件夹。今天一起来看下云炫文件管理器如何快速准确翻译文件夹名&#xff0c;进行批量重命名的技巧。 下图是文件夹名翻译前后的效果图。 英文文件夹名批量翻译成中文…

3Dmax快捷键大全,让你的创作飞起来!附赠3dmax工具箱插件,快来收藏吧!

你是否曾经在3Dmax中因为繁琐的操作而感到困扰&#xff1f; 今天&#xff0c;我将为大家带来一份精心整理的3Dmax常用快捷键宝典&#xff0c;让你在建模、材质编辑、动画制作等各个方面都能游刃有余&#xff0c;让你的创作飞起来&#xff01;&#xff01; &#x1f4a1; 选择与…

27. 深度学习进阶 - 为什么RNN

文章目录 一个柯基的例子为什么RNN or CNN Hi&#xff0c;你好。我是茶桁。 这节课开始&#xff0c;我们将会讲一个比较重要的一种神经网络&#xff0c;它对应了咱们整个生活中很多类型的一种问题结构&#xff0c;它就是咱们的RNN网络。 咱们首先回忆一下&#xff0c;上节课咱…

【计算机网络】TCP|IP协议

目录 前言 什么是TCP/IP协议&#xff1f; TCP/IP协议的层次结构 TCP/IP协议的工作原理 TCP/IP协议的重要性 结语 前言 TCP/IP协议是当今互联网世界中最重要的网络协议之一&#xff0c;它是网络通信的基石&#xff0c;为数据在网络中的传输提供了可靠性和有效性。本文将深…

python编程需要的电脑配置,python编程用什么电脑

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python编程对笔记本电脑配置的要求&#xff0c;python编程对电脑配置的要求有哪些&#xff0c;现在让我们一起来看看吧&#xff01; 学习python编程需要什么配置的电脑 简单的来讲&#xff0c;Python的话普通电脑就可以…

SAP UI5 walkthrough step1 hello word

这里我用的VS Studio 来进行本地化学习 关于SAP UI5是啥&#xff0c;我就不再赘述了&#xff0c;另外还有VS Studio 的安装&#xff0c;请提前做好准备 下面我们直接进入正文 1.首先在你的本地新建一个文件夹&#xff0c;此处我命名为&#xff1a;walkthrough 2.在VS中打开…

【数据结构与算法】JavaScript实现图结构

文章目录 一、图论1.1.图的简介1.2.图的表示邻接矩阵邻接表 二、封装图结构2.1.添加字典类和队列类2.2.创建图类2.3.添加顶点与边2.4.转换为字符串输出2.5.图的遍历广度优先搜索深度优先搜索 2.6.完整实现 一、图论 1.1.图的简介 什么是图&#xff1f; 图结构是一种与树结构…

Java中的反射

反射 Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c; Java 仍是企业和开发人员的首选开发平台。 课程内容的介绍 1. 反射相关的概念 2. 反射的…

HarmonyOS4.0从零开始的开发教程12给您的应用添加弹窗

HarmonyOS&#xff08;十&#xff09;给您的应用添加弹窗 概述 在我们日常使用应用的时候&#xff0c;可能会进行一些敏感的操作&#xff0c;比如删除联系人&#xff0c;这时候我们给应用添加弹窗来提示用户是否需要执行该操作&#xff0c;如下图所示&#xff1a; 弹窗是一种…

AI全栈大模型工程师(二十八)如何做好算法备案

互联网信息服务算法 什么情况下要备案&#xff1f; 对于B2B业务&#xff0c;不需要备案。 但在B2C领域&#xff0c;一切要视具体情况而定。 如果我们自主训练大型模型&#xff0c;这是必要的。 但如果是基于第三方模型提供的服务&#xff0c;建议选择那些已获得备案并且具有较大…

Python脚本打包

一.Windows操作系统 Python脚本打包 1.cmd窗口执行如下指令&#xff1a;pip install pyinstaller C:\Users\ZhuQing>pip install pyinstaller2.执行以下指令验证pyinstaller是否安装成功&#xff08;pyinstaller&#xff09; C:\Users\ZhuQing>pyinstaller3.被打包程序…

frp配置内网穿透步骤

frp配置内网穿透步骤 1.环境准备1.1 云服务器1.2 frp包 2. frp安装2.1 server服务端设置2.2 客户端配置 实现目标通过云服务器ip:8080访问内网电脑启动的web项目localhost:8080 1.环境准备 1.1 云服务器 服务器安装centos7.9, 安全组入口方向开通 7500 7000 8080 8060端口 …

DPDK是什么?DPDK网卡更有优势吗?

近年来&#xff0c;随着数字化的推进&#xff0c;上云成为企业数字化建设的重要指标&#xff0c;用云程度持续深入。可以说&#xff0c;云时代已经来临。 应云而生的DPDK 云时代的一个典型特征&#xff0c;是数据的高速增长。据华为GIV数据&#xff0c;预计2025年全球数据量将…