0001.两数之和

两数之和

简单

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

通过次数1,385,677 提交次数2,805,044


思路:
一开始想到的是先排序,然后从数组两头开始加和,向数组中间靠拢,这样虽然降低了加和过程的时间复杂度,但是排序的过程已远超加和过程的时间复杂度。

在网上看到其他人的解题思路,比如Java和Python,竟然使用 hashmap 的方法来解题,时间复杂度是 O(n):
Java:

import java.util.HashMap;
import java.util.Map;

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int[] indexs = new int[2];

        // 建立k-v ,一一对应的哈希表
        HashMap<Integer,Integer> hash = new HashMap<Integer,Integer>();
        for(int i = 0; i < nums.length; i++){
            if(hash.containsKey(nums[i])){
                indexs[0] = i;
                indexs[1] = hash.get(nums[i]);
                return indexs;
            }
            // 将数据存入 key为补数 ,value为下标
            hash.put(target-nums[i],i);
        }
        // // 双重循环 循环极限为(n^2-n)/2
        // for(int i = 0; i < nums.length; i++){
        //     for(int j = nums.length - 1; j > i; j --){
        //         if(nums[i]+nums[j] == target){
        //            indexs[0] = i;
        //            indexs[1] = j;
        //            return indexs;
        //         }
        //     }
        // }
        return indexs;
    }
}

Python:

class Solution:
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hashmap = {}
        for index, num in enumerate(nums):
            another_num = target - num
            if another_num in hashmap:
                return [hashmap[another_num], index]
            hashmap[num] = index
        return None

我的初版C语言版:

int* two_sum(int* const nums, int numsSize, int target, int* returnSize){
    int* idx = malloc(sizeof(int)*numsSize);
    int* output = malloc(sizeof(int)*2);

    int i, j, tmp;
    for (i = 0; i < numsSize; ++i){
        idx[i] = i;
    }
    bool exchange = false;
    for (i = 0; i < numsSize; ++i){
        for (j = 0; j < numsSize - i - 1; ++j){
            if (nums[idx[j]] > nums[idx[j+1]]){
                tmp = idx[j];
                idx[j] = idx[j+1];
                idx[j+1] = tmp;
                exchange = true;
            }
        }
        if (!exchange){
            break;
        }
    }
    printf("idx:\n");
    print_arr(idx, numsSize);

    int sum;
    bool found = false;
    for (i = 0, j = numsSize - 1; i < j;){
        sum = nums[idx[i]] + nums[idx[j]];
        //printf("sum=%d, idx:%d, %d\n", sum, idx[i], idx[j]);
        if (sum == target){
            output[0] = idx[i];
            output[1] = idx[j];
            found = true;
            break;
        } else if (sum > target){
            --j;
        } else {
            ++i;
        }
    }

    free(idx);
    if (!found){
        free(output);
        *returnSize = 0;
        return NULL;
    }

    *returnSize = 2;
    return output;
}

运行速度:40ms左右;内存:6MB左右

后来仔细思考,发现了排序过程的多余,因为排序的占用的时间复杂度足够完成直接两两加和暴力破解方法。于是直接把排序过程魔改为暴力破解方法,最终版:

int* two_sum(int* const nums, int numsSize, int target, int* returnSize){
    int i, j;
    for (i = 0; i < numsSize - 1; ++i){
        for (j = i + 1; j < numsSize; ++j){
            if (nums[i] + nums[j] == target){
                int* output = malloc(sizeof(int) * 2);
                output[0] = i;
                output[1] = j;
                * returnSize = 2;
                return output;
            }
        }
    }

    * returnSize = 0;
    return NULL;
}

完整程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define bool int
#define false 0
#define true 1

int* two_sum(int* const, int size, int, int*);
void print_arr(int* const, int);

int main(int argc, char** argv){
    int size = 4;
    //int nums[4] = {2,7,11,15};
    //int nums[3] = {3,2,4};
    //int nums[4] = {0,4,3,0};
    //int nums[4] = {-3,4,3,90};
    int nums[4] = {-1,-2,-3,-5};
    int target = -8;
    int returnSize = 0;
    printf("nums:\n");
    print_arr(nums, size);

    int* output = two_sum(nums, size, target, &returnSize);
    printf("output:\n");
    print_arr(output, returnSize);

    return 0;
}

int* two_sum(int* const nums, int numsSize, int target, int* returnSize){
    int i, j;
    for (i = 0; i < numsSize - 1; ++i){
        for (j = i + 1; j < numsSize; ++j){
            if (nums[i] + nums[j] == target){
                int* output = malloc(sizeof(int)*2);
                output[0] = i;
                output[1] = j;
                * returnSize = 2;
                return output;
            }
        }
    }

    * returnSize = 0;
    return NULL;
}

void print_arr(int* const arr, int numsSize){
    printf("[");
    if (numsSize == 0){
        printf("null");
    }else{
        for (int i = 0; i < numsSize; ++i){
            printf("%d", arr[i]);
            if (i < numsSize - 1){
                printf(", ");
            }
        }
    }
    printf("]\n");
}

output:

nums:
[-1, -2, -3, -5]
output:
[2, 3]

运行速度:4ms;内存:5.8M左右

posted @ 2021-04-15 19:42  keep-minding  阅读(44)  评论(0)    收藏  举报