本文首发(其实是补发)于我的个人博客,阅读体验会比 CSDN 好一些。
https://www.ceyewan.top/p/bddf0945.html
正文开始:
在用C语言刷力扣的时候,我们经常会看到这两个东西,
int* returnSize和int** returnColumnSizes。连题目都看不懂,更何况是做题呢?我也是查找了网上零零碎碎的资料和做了蛮多题之后,终于想明白了。遂整理成此文,希望能帮到后来者。个人理解,如有不足,烦请斧正。
首先我们来看一道题,力扣的第 15 题,三数之和。这是笔者第一次接触到这两个东西的题目。
给你一个包含 n 个整数的数组
nums,判断nums中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。注意:答案中不可以包含重复的三元组。
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
输入:nums = []
输出:[]
输入:nums = [0]
输出:[]
0 <= nums.length <= 3000-105 <= nums[i] <= 105/**
* 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().
*/
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
}
题目的意思很明确了,就是这个数组中找到 3 个数,保证 3 个数的和恰好为 target 。我们看默认的代码模板,返回值是一个二阶指针,结合示例,我们可以知道这里需要返回的是一个二维数组。传入的第一个参数 int *nums也很容易理解,就是输入的数组;第二个参数 int numsSize 也容易理解,是数组的长度;那么第三个参数、第四个参数呢?我要处理的是数组,你把数组给我就行了,还多给两个不明不白的东西干啥?
我们看看代码模板的注释,复制到谷歌翻译(大佬可以跳过这一步)。我们可以看到,三句话的意思是:
*returnSize 的数组数组。*returnColumnSizes 数组返回。*columnSizes 数组都必须被 malloced,假设调用者调用 free()。第一句话的数组数组声明意思呢?数组里面的元素是数组,其实就是二维数组。我们还是很容易理解 returnSize 其实就是一个指针的,那么 *returnSize 就代表返回大小,这里的返回大小就是我们要返回的二维数组的行数。还是很容易理解的,毕竟我们不告诉编译器我们的二维数组有多少行,编译器又从何得知呢?
再看第二句话,数组的大小作为 *returnColumnSizes 数组返回。说明 *returnColumnSizes 是一个数组。那么数组的大小是什么意思?前面我们不是说了数组的大小是 *returnSize 吗?怎么又变成 *returnColumnSizes 了?没有搞错吧?确实没有搞错,二维数组除了行还有列啊!那么新的问题又来了,列不是就是3吗?用一个数来表示不就行了?干嘛要用一个数组?这个我只能说,万一呢?万一每一行的长度不一样呢?比如第一行 3 个元素,第二行 2 个元素。力扣就是有这么“严谨”,要求你告诉它每一行有多少个元素。那么你又会有问题了,一个数组,不应该和 nums 一样用指针传入吗?怎么这里是二阶指针?我们先看第三句话。
第三句话,返回的数组和 *columnSizes 数组都必须被 malloced ,假设调用者调用 free() ,重点在于: *columnSizes 数组都必须被 malloced ( *columnSizes 就是 *returnColumnSizes)。这说明 *returnColumnSizes还没初始化呢,还不是一个数组呢。这也很容易理解, *returnColumnSizes 是用来装我们返回的二维数组每一行有多少个元素的(即列数),如果返回 5 行,则 *returnColumnSizes 的长度也得是 5 , 比如说第一个元素是 3 表示二维数组的第一行有 3 个数,第二个元素是 4 表示二维数组的第二行有 4 个数。别人怎么知道你的二维数组有多少行?自然也就不知道应该初始化 *returnColumnSizes 数组为多大了,这一切还得你来。你 malloc 一个数组,自然就会得到一个指向数组的一阶指针,main 函数传进来一个二阶指针指向你这个一阶指针,这样它就能找到你返回的列数组了。
好了,或许你还没懂,不过没关系,我们现在来看看我猜测的 main 函数是什么样子的。
int main()
{
int nums[6] = {-1, 0, 1, 2, -1, -4};
int numsSize = 6;
int returnSize;// 表示返回的二维数组的行数
int **returnColumnSize;// 指向列数组指针的指针
// 注意:列数组在哪我们无从得知,也不需要知道,
// 我们只要知道有个一阶指针指向它就行了,我把它叫做列数组指针
int **ans = threeSum(nums, numsSize, &returnSize, returnColumnSizes);
// &returnSize 引用传值
// 最后一个参数我认为也可以是 int *returnColumnSize,然后传入&returnColumnSizes,效果是一样的
for (int i = 0; i < (*returnSize); i++) {
for (int j = 0; j < (*returnColumnSize)[i]; j++)
printf("%d", ans[i][j]);
printf("\n");
}
return 0;
}
我们再来看看 threeSum 函数里面我们需要做的是什么事。
int **threeSum(int *nums, int numsSize, int *returnSize, int **returnColumnSizes)
{
// ans是二维数组,先假设有100000个答案,准备有100000个一阶指针的空间先
// 每个一阶指针可以指向一个数组,即一个答案
int **ans == (int **)malloc(sizeof(int *) * 100000);
// returnSize是一阶指针, *returnSize是值
*returnSize = 0;// 答案组数为0
while (找到一组答案) {
// malloc一个数组存储答案
int *temp = (int *)malloc(sizeof(int) * 3);// 3个数嘛,3个int
f(把答案写入temp);
ans[(*returnSize)] = temp;// 这两个都是一阶指针
(*returnSize)++;
}
// returnColumnSizes是二阶指针, (*returnColumnSizes)是一阶指针
// 有(*returnSize)行就malloc(*returnSize)个元素
(*returnColumnSizes) = (int *)malloc(sizeof(int) * (*returnSize));
// 本题中每一个元素都是3
for (int i = 0; i < (*returnSize); i++) {
(*returnColumnSizes)[i] = 3;
}
}
// 我们虽然ans数组malloc了100000个空间,但是其实main函数只会用到前(*returnSize)个,多出来的就多出来吧
三重循环暴力法就不写了,这里贴一个双指针的,具体解法力扣的题解讲的比我清楚得多。
# define MAX 100000 // 答案的个数,当然也能用动态扩容
int comp(const void *a, const void *b)
{
return *(int *)a > *(int *)b ? 1 : 0;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
qsort(nums, numsSize, sizeof(int), comp);
int **ans = (int **)malloc(sizeof(int *) * MAX);
*returnSize = 0;
if (numsSize < 3) return ans;
int i = 0;
while (i < numsSize - 2) {
int left = i + 1, right = numsSize - 1;
while (left < right) {
int sum = nums[left] + nums[right] + nums[i];
if (sum == 0) {
int *temp = (int *)malloc(sizeof(int) * 3);
temp[0] = nums[i];
temp[1] = nums[left];
temp[2] = nums[right];
ans[(*returnSize)++] = temp;
}
// 这个地方不能是else if,因为总得改变当前的状态,如果是else if,那么找到了一个答案之后就永远不变了,这是不行的
if (sum < 0)
// 小了,就改变left。跳过重复的同时避免出界
while (left < numsSize - 1 && nums[left] == nums[++left]);
else
// right跳过重复的
while (right > 0 && nums[right] == nums[--right]);
}
// 第一个数字i,同样避免重复和越界
while(i < numsSize - 1 && nums[i] == nums[++i]);
}
*returnColumnSizes = (int *)malloc(sizeof(int) * (*returnSize));
for (int i = 0; i < (*returnSize); i++)
(*returnColumnSizes)[i] = 3;
return ans;
}
希望本文能帮到你,如果还有不明白的地方,欢迎和我交流。
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
我haveaclass它公开了一个字符串值和一个int值(分别是命令输出和退出代码)。除了通过to_s和to_i公开它们之外,我还使用to_str和to_int,如下所示:classStatusdefto_s@outputendalias:to_str:to_sdefto_i@status.exitstatusendalias:to_int:to_iend我的想法是能够在尽可能多的情况下使用这个对象。将其强制转换为字符串或整数会增加可用性。例如,我可以将对象与字符串连接起来:a_string="Outputwas:"+results(我想用这个作为int强制转换的例子,但是Fixnum
我正在通过get发送数据,我需要将其放入一个int数组中以便在查找中使用。这是我的代码:@found=Array.newparams['candidate'].eachdo|c|@found我的网址是这样的http://localhost:3000/export/candidate?candidate[]=3&candidate[]=4&commit=Export如果它有任何不同,我将它用于此查找@candidate=Candidate.find(:all,:conditions=>["candidates.idIN?",@found])但目前它并没有把它放在一个真正的数组中,因为我得
一、什么是MQTT协议MessageQueuingTelemetryTransport:消息队列遥测传输协议。是一种基于客户端-服务端的发布/订阅模式。与HTTP一样,基于TCP/IP协议之上的通讯协议,提供有序、无损、双向连接,由IBM(蓝色巨人)发布。原理:(1)MQTT协议身份和消息格式有三种身份:发布者(Publish)、代理(Broker)(服务器)、订阅者(Subscribe)。其中,消息的发布者和订阅者都是客户端,消息代理是服务器,消息发布者可以同时是订阅者。MQTT传输的消息分为:主题(Topic)和负载(payload)两部分Topic,可以理解为消息的类型,订阅者订阅(Su
TCL脚本语言简介•TCL(ToolCommandLanguage)是一种解释执行的脚本语言(ScriptingLanguage),它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。TCL经常被用于快速原型开发,脚本编程,GUI和测试等方面。•实际上包含了两个部分:一个语言和一个库。首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。由于TCL的解释器是用C\C++语言的过程库实现的,因此在某种意义上我们又可以把TCL看作C库,这个库中有丰富的用于扩展TCL命令的C\C++过程和函数,所以,Tcl是
我正在重构一个西洋跳棋程序,我正在尝试将玩家移动请求(例如以“3、3、5、5”的形式)处理到一个int数组中。我有以下方法,但感觉不像我所知道的那样像Ruby:deftranslate_move_request_to_coordinates(move_request)return_array=[]coords_array=move_request.chomp.split(',')coords_array.each_with_indexdo|i,x|return_array[x]=i.to_iendreturn_arrayend我用它进行了以下RSpec测试。it"translatesa
如何将字符串:s='23534'转换为这样的数组:a=[2,3,5,3,4]有没有一种方法可以遍历ruby中的字符并将它们中的每一个转换为to_i或者甚至像Java一样将字符串表示为char数组,然后转换所有字符to_i如您所见,我在字符串中没有这样的分隔符,,我在SO上找到的所有其他答案都包含一个分隔符。 最佳答案 一个简单的衬里是:s.each_char.map(&:to_i)#=>[2,3,5,3,4]如果您希望在字符串不只包含整数时显示错误,您可以这样做:s.each_char.map{|c|Integer(c)}这会引
如何在ruby中将十六进制字符串转换为32位有符号整数?例如a="fb6d8cf1"#hexstring[a].pack('H*').unpack('l')#fromthedocumentationitunpackstoits32bitsignedint它转换为-242455045但实际答案是-76706575你能指出我做错了什么吗? 最佳答案 您似乎遇到了字节序问题。这给出了期望的结果:[a].pack("H*").unpack("l>")#=>[-76706575]["038a67f90"].pack("H*").unpac
开门见山|拉取镜像dockerpullelasticsearch:7.16.1|配置存放的目录#存放配置文件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/config#存放数据的文件夹mkdir-p/opt/docker/elasticsearch/node-1/data#存放运行日志的文件夹mkdir-p/opt/docker/elasticsearch/node-1/log#存放IK分词插件的文件夹mkdir-p/opt/docker/elasticsearch/node-1/plugins若你使用了moba,直接右键新建即可如上图所示依次类推创建
文章目录概念索引相关操作创建索引更新副本查看索引删除索引索引的打开与关闭收缩索引索引别名查询索引别名文档相关操作新建文档查询文档更新文档删除文档映射相关操作查询文档映射创建静态映射创建索引并添加映射概念es中有三个概念要清楚,分别为索引、映射和文档(不用死记硬背,大概有个印象就可以)索引可理解为MySQL数据库;映射可理解为MySQL的表结构;文档可理解为MySQL表中的每行数据静态映射和动态映射上面已经介绍了,映射可理解为MySQL的表结构,在MySQL中,向表中插入数据是需要先创建表结构的;但在es中不必这样,可以直接插入文档,es可以根据插入的文档(数据),动态的创建映射(表结构),这就