LeetCode题解--1. Two Sum(和为S的两个数字)

来源:互联网 发布:数据结构kmp算法代码 编辑:程序博客网 时间:2024/05/16 11:15

链接


题目地址:https://leetcode.com/problems/two-sum/
Github代码:https://github.com/gatieme/LeetCode/tree/master/001-TwoSum
CSDN题解:http://blog.csdn.net/gatieme/article/details/50596965

描述


给定一个整数数组,找出其中两个数满足相加等于你指定的目标数字。

要求:这个函数twoSum必须要返回能够相加等于目标数字的两个数的索引,且index1必须要小于index2。请注意一点,你返回的结果(包括index1和index2)都不是基于0开始的,即自1开始

你可以假设每一个输入肯定只有一个结果。

举例:
输入:numbers={3, 2, 4}, target = 6
输出:index1 = 2, index2 = 3

暴力解法O(n^2)


首先是最暴力的方法,使用双层循环,对于数组nums中的每一个数据nums[left]判断后面是否有某个数nums[right],使得

nums[left] + nums[right] ==target
即 num[right] = target - nums[left]

/* * * Note: The returned array must be malloced, assume caller calls free(). * */#include <stdio.h>#include <stdlib.h>#include <malloc.h>//#define DEBUGint* twoSum(int* nums,      /*  the pointer which point to the array  */            int numsSize,   /*  the size of the array  */            int target)     /*  the sum of the two num  */{    int *answer = (int *)malloc(sizeof(int) * 2);    for(int left = 0; left < numsSize; left++)  // 对于每一个数据    {        // 循环其后面的数据看nums[left] + nums[right] == target是否成立        // 其实就是看target - nums[right]在不在数组中        for(int right = left + 1; right < numsSize; right++)        {            if(nums[left] + nums[right] == target)            {                answer[0] = left + 1;                answer[1] = right + 1;                break;            }        }    }    return answer;}#ifdef DEBUGint main(void){    int nums[5] = {3, 2, 4};    int *answer = NULL;    answer = twoSum(nums, 3, 6);    printf("[%d, %d]\n", answer[0], answer[1]);}#endif

进阶解法–基于排序O(nlogn)


#include <stdio.h>#include <stdlib.h>#include <malloc.h>//#define DEBUG/////////////////////////////////////////////////////////////////////////////////  快速排序--QuickSort///  http://www.cnblogs.com/RootJie/archive/2012/02/13/2349649.html//////////////////////////////////////////////////////////////////////////////#include <stdio.h>#include <time.h>#define MAX_SIZE 20000#define SWAP(x, y) {int t=x; x=y; y=t;}void QuickSort(int *array, int left, int right);int Partition(int *array, int left, int right);int position[MAX_SIZE]; //  用于存储位置信息int InitPosion(int *position, int length){    for(int pos = 0; pos < length; pos++)    {        position[pos] = pos + 1;    }}int Partition(int *array, int left, int right){    int pivot = array[left];    while (left < right)    {        while (left < right && array[right] >= pivot)        {            --right;        }        SWAP(array[left], array[right]);        SWAP(position[left], position[right]);        while (left < right && array[left] <= pivot)        {            ++left;        }        SWAP(array[right], array[left]);        SWAP(position[left], position[right]);    }    return left;}void QuickSort(int *array, int left, int right){    int pivot;    if (left < right)    {        pivot = Partition(array, left, right);        QuickSort(array, left, pivot - 1);        QuickSort(array, pivot + 1, right);    }}int cmp(const void *left, const void *right){    int *left_num = (int *)left;    int *right_num = (int *)right;    return (*left_num - *right_num);    //qsort(nums, numsSize, sizeof(nums[0]), cmp);}int* twoSum(int* nums,      /*  the pointer which point to the array  */            int numsSize,   /*  the size of the array  */            int target)     /*  the sum of the two num  */{    //qsort(nums, numsSize, sizeof(nums[0]), cmp);    InitPosion(position, numsSize);#ifdef DEBUG       printf("Before Quick Sort : \n");    printf("Array    : ");    for(int pos = 0; pos < numsSize; pos++)    {        printf("%3d", nums[pos]);    }    printf("\n");    printf("Position : ");    for(int pos = 0; pos < numsSize; pos++)    {        printf("%3d", position[pos]);    }    printf("\n");#endif      QuickSort(nums, 0, numsSize - 1);#ifdef DEBUG       printf("After Quick Sort : \n");    printf("Array    : ");    for(int pos = 0; pos < numsSize; pos++)    {        printf("%3d", nums[pos]);    }    printf("\n");    printf("Position : ");    for(int pos = 0; pos < numsSize; pos++)    {        printf("%3d", position[pos]);    }    printf("\n");#endif      int *answer = (int *)malloc(sizeof(int) * 2);    int left = 0, right = numsSize - 1, sum;    while(left < right)    {        sum = nums[left] + nums[right];#ifdef DEBUG        printf("[%d, %d], %d + %d = %d\n",            left, right,            nums[left], nums[right], sum);#endif          if(sum == target)        {#ifdef DEBUG            printf("[%d, %d], %d + %d = %d\n",                left, right,                nums[left], nums[right], target);#endif            break;        }        else if(sum < target)        {#ifdef DEBUG            printf("[%d, %d], %d + %d = %d\n",                left, right,                nums[left], nums[right], target);#endif            left++;        }        else if(sum > target)        {#ifdef DEBUG            printf("[%d, %d], %d + %d = %d\n",                left, right,                nums[left], nums[right], target);#endif            right--;        }    }    if(position[left] < position[right])    {        answer[0] = position[left];        answer[1] = position[right];    }    else    {        answer[0] = position[right];        answer[1] = position[left];    }    return answer;}#ifdef DEBUGint main(void){    int nums[5] = {-1, -2, -3, -4, -5};    int *answer = NULL;    answer = twoSum(nums, 5, -8);    printf("[%d, %d]\n", answer[0], answer[1]);}#endif

优化解法


前面我们的算法是

对于数组nums中的每一个数据nums[left]判断后面是否有某个数nums[right],使得

nums[left] + nums[right] ==target
即 num[right] = target - nums[left]

循环每一个nums[left]的时间复杂度为O(N)
现在我们要是能在查找 num[right]上提高效率,就能提高整个算法的效率。

我们在处理的时候,不仅需要知道当前数据,还需要知道数据的位置,而又需要提高查找的效率,因此可以使用map映射或者哈希表

对一个字符串算出hash码后,这个hash码相当于一个指针,就可以直接指向其存储位置,从而是O(1)的时间复杂度。

#include <iostream>#include <vector>#include <unordered_map>///==================/// 思路如下///==================////// 采用哈希表或者map来做/// 对于数组numbers中的每一个数numbers[i]/// 判断target - numbers[i]在不在哈希表中/// 如果在那么就返回这两个叔的位置/// 如果不在就继续往下找, 同时将当前的数存入哈希表中#define DEBUGclass Solution{public:    std::vector<int> twoSum(std::vector<int> &numbers,  //  the array of the number                            int target) //  the sum of the two num    {        std::unordered_map<int, int> mp;        std::vector<int> ans;        //  用哈希表来做        for(int i = 0; i < numbers.size(); i ++)    //  对于数组中的每个数据        {            //  判断target - numbers[i]在不在            if(mp.count(target - numbers[i]))   //  如果在里面               {                //  那么numbers中就存在两个数和为target                ans.push_back(mp[target - numbers[i]] + 1);                 ans.push_back(i + 1);                break;            }            if(mp.count(numbers[i]) != 1)            {                mp[numbers[i]] = i;            }        }        return ans;    }};#ifdef DEBUGint main(void){    std::vector<int> numbers = {3, 2, 4};    int target = 6;    Solution solu = Solution();    std::cout <<"[" <<solu.twoSum(numbers, target)[0] <<", " <<solu.twoSum(numbers, target)[1] <<"]" <<std::endl;;}#endif

python


python中的字典有和map一样的功能

#!/usr/bin/env python#coding=utf-8##  找出数组中的两个数,这两个数和为target#  扫到x时看前面Hash的数里有没有target-x,#  然后将x也放进Hash表。class Solution:    # @return a tuple, (index1, index2)    def twoSum(self, num, target):        # python中字典dict类似于map的        dict = {}        for i in range(len(num)):   #  对于每一个num            # 判断target - num[i]在不在在字典中            if dict.get(target - num[i], None) == None: #如果不在                dict[num[i]] = i   # 将该数存入字典中            else:                # 否则这两个数的和为target, 则返回                return (dict[target - num[i]] + 1, i + 1)if __name__ == "__main__" :    num = [3, 2, 4]    target = 6    solution = Solution()    print solution.twoSum(num, target)
0 0
原创粉丝点击