Task1——两数之和
程序员文章站
2022-04-08 12:59:31
...
目录
前言:
本题的采用C语言解决问题,并使用了两种解题思路。
题目:
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
暴力解题过程:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
int* idx = (int*)malloc(sizeof(int)*2);
for(int i=0; i<numsSize-1; i++)
{
for(int j=i+1; j<numsSize; j++)
{
if(nums[i]+nums[j] == target)
{
idx[0] = i;
idx[1] = j;
returnSize[0] = 2;
return idx;
}
}
}
returnSize = 0;
return 0;
}
解题思路:
- 题目中表明,传入的数组中最多有一个有效答案,所以对数组进行遍历即可。
- 因为找两数之和,所以从第一个元素开始遍历至最后一个元素,最多的遍历次数为n!(其中n为数组长度)
解题结果:
哈希解题过程:
#include <math.h>
#define hash_fn(key, size) (abs(key%size)+1) // 使用0判断hash是否填充
#define prob_fn(key, size) (abs(key%size)+1) // 使用0判断hash是否填充
typedef struct _HashTable_t
{
int hash; // 用于判断当前哈希数组元素是否有填充,若为0即为无填充
int key; // 键 -- 唯一性
int val; // 值 -- 存放被查询元素
}HashTable_t;
void HashInsert(HashTable_t* t, int tSize, int key, int val)
{
int hash = hash_fn(key, tSize);
int idx = hash;
// 寻找哈希表中为0的数组元素
while (t[idx].hash)
{
idx = prob_fn(idx, tSize);
}
// 将目标哈希数组填充
t[idx] = (HashTable_t){ hash, key, val };
}
#include <stdbool.h>
bool HashFind(HashTable_t* t, int size, int key, int* val)
{
// 获取指定键的哈希值
int hash = hash_fn(key, size);
int idx = hash;
// 寻找hash非0,且键相等的元素
while (t[idx].hash && t[idx].key != key)
{
idx = prob_fn(idx, size);
}
val[0] = t[idx].val;
// 返回hash值是否相同
return t[idx].hash == hash;
}
#include <stdlib.h>
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
int* p = (int*)malloc(sizeof(int) * 2);
// 由于传进来的参数中包含数组的长度
// 所以分配足够的哈希空间
int tSize = numsSize * 2;
HashTable_t *t = calloc(tSize+1, sizeof(HashTable_t));
for (int i = 0; i < numsSize; i++)
{
// 寻找数值为 (target-nums[i]) 的元素的索引
if (HashFind(t, tSize, target - nums[i], &p[1]))
{
// 找到后,将索引存储于缓存 p 中
p[0] = i;
*returnSize = 2;
free(t);
return p;
}
else
{
// 否则将键值对 -- nums[i]:i 存放于哈希表中
HashInsert(t, tSize, nums[i], i);
}
}
*returnSize = 0;
free(p);
free(t);
return 0;
}
解题思路:
- 本题可以换一个角度考虑:已知target和nums[i],寻找两者之差的数值是否在nums中,并且获得其坐标值
- 问题就转换为数据搜索查询
- 哈希表(散列表)既有数组快速查询的优点,又有链表快速插入、删除的优点。在数据存储查询的领域中十分常用
- 借鉴哈希表和本题的思路,将已知元素nums[n]作为键(本题中所有的nums必不重复)通过哈希算法填充到指定的哈希表中,可以实现时间为O(1)的查询速度
- 用于本题的哈希算法 #define(key, size) ((key%size) + 1) // 0作为判断非空,所以数值整体+1
- 实现哈希的插入、寻找算法
- 循环调用即可
解题结果:
总结与思考:
通过上述两种解题思路的比较可以发现,暴力解题思路简单,并且实现起来很方便,但是在时间上面却输的特别惨。采用哈希表的数据结构与算法,在查找和插入元素过程中具有显著优势,因此在解题时间上面有“飞”的感觉。
通过本题,get到一个新技能,就是哈希表的运用。
来源:
https://leetcode-cn.com/problems/two-sum/
参考:
- 关于哈希表的思路参考学习了力口中的评论
- 哈希表原理说明:https://blog.csdn.net/yyyljw/article/details/80903391
下一篇: python可视化决策树