力扣|找出和所对应的两数的下标

从零开始刷力扣(bushi

题目放在这:

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

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

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

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109

只会存在一个有效答案

放一个分割线在这:


我自己也是C语言复建,没有系统学习过数据结构,所以第一反应真就是暴力破解(见笑了)

也就是依次将数组的两个元素相加,和目标数做对比

因为只有一个有效答案,那么就可以在检索到和等于目标数数,直接输出对应的坐标

如果遍历结束没有得到结果,则输出NULL

借一下leecode的标准答案,这边我自己加上了前期的输入输出语句,这样方便看到结果:

cs 复制代码
#include <stdio.h>
#include <stdlib.h>

int *twoSum(int *nums, int numsSize, int target, int *returnSize);

int main() {
	int *p, *returnSize;
	int nums[10];
	int numsSize = 0, target = 0;
	*returnSize = 2;

	printf("找出数组中和为目标数的两个元素的下标:\n请输入数组的长度(不超过十)\n");
	scanf("%d", &numsSize);
	printf("请输入数组的内容,并用回车分隔\n");
	for (int i = 0; i < numsSize; i++) {
		scanf("%d", &nums[i]);
	}
	printf("您输入的数组内容为:nums[]=");
	for (int i = 0; i < numsSize; i++) {
		printf("%d ", nums[i]);
	}
	printf("请输入您的目标数:\n");
	scanf("%d", &target);
	p = twoSum(nums, numsSize, target, returnSize);
	if (p != NULL) {
		printf("您的目标数对应的坐标下标为:");
		printf("%d ", p[0]);
		printf("%d", p[1]);
	} else
		printf("您的目标数不能被数组中的任何两个数相加得到。");

	return 0;
}

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) {
				int *ret = (int *)malloc(sizeof(int) * 2);
				ret[0] = i, ret[1] = j;
				*returnSize = 2;
				return ret;
			}
		}
	}
	*returnSize = 0;
	return NULL;
}

简单讲一点:

1、<stdio.h>头文件,翻译为standard input output

程序中用到的scanf、printf,都需要使用标准的输入输出库

2、<stdlib.h>头文件,和存储、空间分配密切相关的一个函数

程序中用到的malloc函数,用来分配内存空间,出自于这个头文件

类似的还有calloc、free、realloc函数等,感兴趣的可以看一看

3、malloc函数:

函数原型:void * malloc(unsigned size);

功能是分配size字节的存储区。程序中需要两个int的空间所以乘2

默认的类型是void*,由于我设定了ret为int*类型,所以这里强制类型转换为int*

(leecode标准答案是没有这个强制转换的,其实我也有印象这一步可以自动转换,但是我用的Dev C++报错)

再放一个分割线:


那么肯定不可能就到此为止了,在今年校招(2024届校招)中,不知道大家有没有关注腾讯的招聘,直播间提到的就是这个问题。

不过大佬显然指的是用哈希表

什么是哈希表?

哈希表是一种数据结构,提供了快速的插入操作和查找操作

不管哈希表有多少数据,插入和查找的时间复杂度都是O(1),查找速度非常快

不过,哈希表基于数组,一旦数组被填满,性能就大不如前。

关于哈希表,推荐一个视频:

『教程』哈希表是个啥?_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1qR4y1V7g6/?spm_id_from=333.337.search-card.all.click&vd_source=86629babf8e8eb6ebc7b7475ab3f61a2简单理解为:用时间换空间

先放代码(后面有详细解释,这里方便想自学的大佬):

cs 复制代码
struct hashTable {
    int key;
    int val;
    UT_hash_handle hh;
};

struct hashTable* hashtable;

struct hashTable* find(int ikey) {
    struct hashTable* tmp;
    HASH_FIND_INT(hashtable, &ikey, tmp);
    return tmp;
}

void insert(int ikey, int ival) {
    struct hashTable* it = find(ikey);
    if (it == NULL) {
        struct hashTable* tmp = malloc(sizeof(struct hashTable));
        tmp->key = ikey, tmp->val = ival;
        HASH_ADD_INT(hashtable, key, tmp);
    } else {
        it->val = ival;
    }
}

int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
    hashtable = NULL;
    for (int i = 0; i < numsSize; i++) {
        struct hashTable* it = find(target - nums[i]);
        if (it != NULL) {
            int* ret = malloc(sizeof(int) * 2);
            ret[0] = it->val, ret[1] = i;
            *returnSize = 2;
            return ret;
        }
        insert(nums[i], i);
    }
    *returnSize = 0;
    return NULL;
}

然后咱们就来详细解释这个代码。

已知,用哈希表查询,首先将要查找的东西作为参数进入一个函数,得到一个确定的数字

该数字就是哈希表中,查询结果的地址。

这样,本来我们需要一个个查询、比较的,现在只需要经过一次函数计算,一次查找。

将目光回到代码上:

cs 复制代码
struct hashTable {
    int key;
    int val;
    UT_hash_handle hh;
};

给出哈希表的结构,这个在哈希表的使用中是确定的,一般第一个是数值,第二个是位置(原本数组中的位置),第三个是一个句柄,链接前一个和后一个哈希表

cs 复制代码
struct hashTable* hashtable;

struct hashTable* find(int ikey) {
    struct hashTable* tmp;
    HASH_FIND_INT(hashtable, &ikey, tmp);
    return tmp;
}

建立一个哈希表的指针,并且设置一个寻找函数

输入参数是我们要找的结果,并内置了HASH_FIND_INT函数

这个是头文件中包含的函数,主要参数有三个,

第一个就当默认参数,第二个是要找的值,第三个是哈希表的指针(做返回值用)

该函数的意义是:

找到ikey对应的值,如果哈希表中没有,tmp=NULL

如果找到了对应的值,tmp的第一个值为ikey,第二个是ikey对应的哈希表的val

简单来说就是一个查询操作,如果没有返回NULL,如果有返回对应的数值和位置

cs 复制代码
void insert(int ikey, int ival) {
    struct hashTable* it = find(ikey);
    if (it == NULL) {
        struct hashTable* tmp = malloc(sizeof(struct hashTable));
        tmp->key = ikey, tmp->val = ival;
        HASH_ADD_INT(hashtable, key, tmp);
    } else {
        it->val = ival;
    }
}

定义一个插入函数

find函数就是我们上面提到的寻找函数,会返回一个哈希表的指针,

如果返回的指针为NULL,也就是哈希表中没有我们要找的值,会再次定义一个分配了一个哈希表空间的指针tmp,并将对应的数值,以及数值在原本数组中的数值赋值给新建的哈希表

运用HASH_ADD_INT函数将这个新建的数据增加到哈希表中

如果返回的指针有数值,也就是哈希表中已经存在对应的结果了,找到了,那就更方便,直接记录

cs 复制代码
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
    hashtable = NULL;
    for (int i = 0; i < numsSize; i++) {
        struct hashTable* it = find(target - nums[i]);
        if (it != NULL) {
            int* ret = malloc(sizeof(int) * 2);
            ret[0] = it->val, ret[1] = i;
            *returnSize = 2;
            return ret;
        }
        insert(nums[i], i);
    }
    *returnSize = 0;
    return NULL;
}

这是函数的主体

按照原始数组的顺序循环,依次查找target-nums[i]的结果,刚开始都是向哈希表内添加数,直到找到对应的结果

因为这里假设只存在唯一解,所以就没有必要考虑多种情况

简单画一个执行的逻辑吧:

相关推荐
浮生如梦_2 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师4 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
师太,答应老衲吧4 小时前
SQL实战训练之,力扣:2020. 无流量的帐户数(递归)
数据库·sql·leetcode
捕鲸叉4 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer4 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
wheeldown5 小时前
【数据结构】选择排序
数据结构·算法·排序算法
观音山保我别报错6 小时前
C语言扫雷小游戏
c语言·开发语言·算法
TangKenny7 小时前
计算网络信号
java·算法·华为
景鹤7 小时前
【算法】递归+深搜:814.二叉树剪枝
算法
iiFrankie7 小时前
SCNU习题 总结与复习
算法