LeetCode: Problem 1, Two Sum

LeetCode: 2 sum


题目链接: https://leetcode.com/problems/two-sum

  作为一名学院小学渣,被dalao推荐来写leetcode,第一题就耗费了我好久时间。虽说我就是那种经典的四级词汇只记得abandon的那种,但是还是有想尽量努力长期刷下去的想法,就想尝试长期写博客,希望自己能在这里坚持下去吧。
  小白看这一题第一反应就是暴力遍历,于是很快码完,然后交了这么一份代码上去:

int* twoSum(int* nums, int numsSize, int target) {
    int i,j;
    int *index;
    index = (int *)malloc(sizeof(int) * 2);

    for(i = 0;i < numsSize;i++){
        for(j = i + 1;j < numsSize;j++){
            if(nums[i] + nums[j] == target){
                
                index[0] = i;
                index[1] = j;
                break;

            }
        }
    }
    return index;
    
}

  这份代码提交了多次,时间一般都在150ms左右徘徊,内存在7.7MB上下变化。这里如果换成leetcode-cn,时间会变成260ms左右,很奇怪,难道leetcode-cn和leetcode本家的测试用例还有不同吗emmm。
提交的代码情况
  当然这肯定不是最好的解法,一开始我考虑过库排序再遍历,但是c语言qsort会把下标打乱,一般这样就必须用结构体来储存下标了,感觉这样会不会更加麻烦,就没有去尝试
  一般暴力遍历最大的问题是时间问题,所以一般优化算法都是采取空间换时间的方法。一时脑子里没想到什么比较好的方法,于是去网上看了下,发现大部分都提到用哈希表。于是自己写了份哈希表代码,一开始一直都是wrong answer,代码如下:

int* twoSum(int* nums, int numsSize, int target) {
    int *index, i, *HashTable;
    int min=nums[0], max, len;
    index = (int *)malloc(sizeof(int)*2);
    for(i = 1;i < numsSize;i++){
        if(nums[i] < min) min = nums[i];
    }
    max = target - min;
    len = max - min + 1;
    HashTable = (int *) malloc(sizeof(int) * len);
    for(i = 0;i < len;i++){
        HashTable[i] = -1;
    }
    
    for(i = 0;i < numsSize;i++){
        if(nums[i] - min< len){
            HashTable[nums[i] - min] = i;
            if(HashTable[max - nums[i]] != -1){
                index[0] = HashTable[max - nums[i]];
                index[1] = i;
                break;
            }
        }
    }
    return index;
}

报错:
Wrong Answer
  这里还是太天真,导致他读到了同一个位置的数字相加了。需要把先判断哈希表相应位置是否存在可以相加为target的数值之后给对应位置赋值。后来修改代码如下:

int* twoSum(int* nums, int numsSize, int target) {
    int *index, i, *HashTable;
    int min=nums[0], max, len;
    index = (int *)malloc(sizeof(int)*2);
    for(i = 1;i < numsSize;i++){
        if(nums[i] < min) min = nums[i];
    }
    max = target - min;
    len = max - min + 1;
    HashTable = (int *) malloc(sizeof(int) * len);
    for(i = 0;i < len;i++){
        HashTable[i] = -1;
    }
    
    for(i = 0;i < numsSize;i++){
        if(nums[i] - min< len){
            if(HashTable[max - nums[i]] != -1){
                index[0] = HashTable[max - nums[i]];
                index[1] = i;
                break;
            }
            HashTable[nums[i] - min] = i;
        }
    }
    return index;
}

这次就成功了。但是不知道为何我的时间复杂度没提升多少,空间复杂度倒是蹭的一下上去了。后来自己再想,决定用结构体排序,排序之后从两端逼近target。这次的代码就在时间上有大提升,空间上也基本没有变化太大。

struct node {
    int val;
    int place;
}Node;
int cmp(const void* a, const void* b) {
    return ((struct node*)a)->val - ((struct node*)b)->val;
}
int* twoSum(int* nums, int numsSize, int target) {
    int i = 0;
    int begin = 0, end = numsSize - 1;
    int* index;
    struct node* nodes = (struct node*)malloc(numsSize * sizeof(struct node));
    for(i = 0; i < numsSize; i++) {
        nodes[i].val = nums[i];
        nodes[i].place = i;
    }
    qsort(nodes, numsSize, sizeof(struct node), cmp);
    while(begin < end) {
        if(nodes[begin].val + nodes[end].val == target) {
            index = (int*)malloc(sizeof(int) * 2);
            index[0] = nodes[begin].place;
            index[1] = nodes[end].place;
            break;
        }
        else if(nodes[begin].val + nodes[end].val > target)
            end--;
        else
            begin++;            
    }
    return index;
}


最后的结果:
最后的结果
这里如果使用leetcode-cn的话会变成52ms,看来可能两个网站真的有所不同?还是说是网络传输问题。。等以后学习了再看吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
给定一个整数数组 nums 和一个目标值 target,要求在数组中找出两个数的和等于目标值,并返回这两个数的索引。 思路1:暴力法 最简单的思路是使用两层循环遍历数组的所有组合,判断两个数的和是否等于目标值。如果等于目标值,则返回这两个数的索引。 此方法的时间复杂度为O(n^2),空间复杂度为O(1)。 思路2:哈希表 为了优化时间复杂度,可以使用哈希表来存储数组中的元素和对应的索引。遍历数组,对于每个元素nums[i],我们可以通过计算target - nums[i]的值,查找哈希表中是否存在这个差值。 如果存在,则说明找到了两个数的和等于目标值,返回它们的索引。如果不存在,将当前元素nums[i]和它的索引存入哈希表中。 此方法的时间复杂度为O(n),空间复杂度为O(n)。 思路3:双指针 如果数组已经排序,可以使用双指针的方法来求解。假设数组从小到大排序,定义左指针left指向数组的第一个元素,右指针right指向数组的最后一个元素。 如果当前两个指针指向的数的和等于目标值,则返回它们的索引。如果和小于目标值,则将左指针右移一位,使得和增大;如果和大于目标值,则将右指针左移一位,使得和减小。 继续移动指针,直到找到两个数的和等于目标值或者左指针超过了右指针。 此方法的时间复杂度为O(nlogn),空间复杂度为O(1)。 以上三种方法都可以解决问题,选择合适的方法取决于具体的应用场景和要求。如果数组规模较小并且不需要考虑额外的空间使用,则暴力法是最简单的方法。如果数组较大或者需要优化时间复杂度,则哈希表或双指针方法更合适。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值