Leetcode刷题记录:1 两数之和(数组 哈希)

Leetcode刷题记录:1 两数之和(数组 哈希)

题干:

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

  1. 暴力解法:用两个for循环嵌套,一一枚举,直至发现和为target,返回这两个数的下标。
/**
 1. 采用动态数组的方式;
 2. Note: The returned array must be malloced, assume caller calls free().
 */
int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int i;
    int j;
    int *ret;
    for(i=0;i<numsSize;i++){
        for(j=i+1;j<numsSize;j++){
            if(nums[i]+nums[j]==target){
                ret=(int*)malloc(sizeof(int)*2);
                ret[0]=i;
                ret[1]=j;
                *returnSize=2;
                return ret;
            }
        }
    }
    *returnSize=0;
    return 0;
}

注:该方法时间复杂度为O(n^2),空间复杂度为O(1)。

  1. 哈希表法:对暴力解法进行改进,第二个for循环即在找target-nums[i]中时间复杂度为O(n),用哈希表时间复杂度O(1)来实现target-nums[i]的查找。

整体思路为:
对数组遍历,针对第一个for循环的元素nums[i],计算出其和目标值target之间的差值,即anotherNum=target-nums[i]。
之后在哈希表中查找anotherNum,如果存在,则表示找到了两个数,其和等于target。若不存在,则将当前考察的元素值作为key,其对应的索引 i 作为value,存入哈希表中。

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
struct Hashmap{
    int key;
    int value;
    UT_hash_handle hh;
};

struct Hashmap* hashtable;

struct Hashmap* find(int ikey){
    struct Hashmap* temp;
    HASH_FIND_INT(hashtable,&ikey,temp);
    return temp;
}

void insert(int ikey,int ivalue){
    struct Hashmap* temo;
    temo=find(ikey);
    if(temo==NULL){
        struct Hashmap* addhash=malloc(sizeof(struct Hashmap));
        addhash->key=ikey;
        addhash->value=ivalue;
        HASH_ADD_INT(hashtable,key,addhash);
    }
    else{
        temo->value=ivalue;
    }
}


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

注:时间复杂度为O(n),空间复杂度为O(n)。
两次运行时间对比如下图:
前后执行时间与内存消耗对比明显由上图前后执行时间内存消耗对比明显

补充:

哈希法代码使用了uthash代码。uthash
是C的开源代码,它实现了常见的hash操作函数,例如构建、查找、插入、删除等。该套开源代码采用宏的方式实现hash函数的相关功能,支持C语言的任意数据结构最为key值,甚至可以采用多个值作为key,无论是自定义的struct还是基本数据类型,需要注意的是不同类型的key其操作接口方式略有不通。
使用uthash代码时只需要包含头文件"uthash.h"即可。由于该代码采用宏的方式实现,所有的实现代码都在uthash.h文件中,因此只需要在自己的代码中包含该头文件即可。
uthash的英文使用文档介绍为:
http://troydhanson.github.io/uthash/userguide.html#_add_item

错误记录:

  • 错误记录1:

在上图第二次截图中,运行错误是因为twoSum函数中为对hashtable进行初始化
原函数为:

int* twoSum(int* nums, int numsSize, int target, int* returnSize){
    int i;
    int j;
    int anothernumber;
    int *ret;
    for(i=0;i<numsSize;i++){
        anothernumber = target-nums[i];
        struct Hashmap* hashelement=find(anothernumber);
        if(hashelement!=NULL){
            ret=malloc(sizeof(int)*2);
            ret[0]=hashelement->value;
            ret[1]=i;
            *returnSize=2;
            return ret;
        }
        insert(nums[i],i);
    }
    *returnSize=0;
    return NULL;
}

加入初始化

hashtable=NULL;

之后运行正确。
输入为:
[3,3]
6
我的输出:
[0,0]
正确输出:
[0,1]

原因猜测是上一个测试的影响,具体还不清楚,等明白了再补充…

  • 错误记录2:

HASH_ADD_INT(hashtable,key,addhash);
这个函数第一个参数是哈希表,第二个参数是键字段的名称,第三个参数是要增加的指针结构,这个地方如果写成
HASH_ADD_INT(hashtable,ikey,addhash);就会输出NULL。
HASH_ADD_INT()函数要注意!!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值