Task1——两数之和

目录

前言:

题目:

示例:

暴力解题过程:

解题思路:

解题结果:

哈希解题过程:

解题思路:

解题结果:

总结与思考:

来源:

参考:


前言:

本题的采用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;
}

解题思路:

  1. 题目中表明,传入的数组中最多有一个有效答案,所以对数组进行遍历即可。
  2. 因为找两数之和,所以从第一个元素开始遍历至最后一个元素,最多的遍历次数为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;
}

解题思路:

  1. 本题可以换一个角度考虑:已知target和nums[i],寻找两者之差的数值是否在nums中,并且获得其坐标值
  2. 问题就转换为数据搜索查询
  3. 哈希表(散列表)既有数组快速查询的优点,又有链表快速插入、删除的优点。在数据存储查询的领域中十分常用
  4. 借鉴哈希表和本题的思路,将已知元素nums[n]作为键(本题中所有的nums必不重复)通过哈希算法填充到指定的哈希表中,可以实现时间为O(1)的查询速度
  5. 用于本题的哈希算法 #define(key, size) ((key%size) + 1) // 0作为判断非空,所以数值整体+1
  6. 实现哈希的插入、寻找算法
  7. 循环调用即可

解题结果:

总结与思考:

通过上述两种解题思路的比较可以发现,暴力解题思路简单,并且实现起来很方便,但是在时间上面却输的特别惨。采用哈希表的数据结构与算法,在查找和插入元素过程中具有显著优势,因此在解题时间上面有“飞”的感觉。

通过本题,get到一个新技能,就是哈希表的运用。

来源:

https://leetcode-cn.com/problems/two-sum/

参考:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值