[Leetcode] 1. Two Sum

本文介绍了如何在整数数组中寻找两个数使它们的和等于特定目标值的问题。提供了两种解决方案,一种是O(n^2)的暴力搜索方法,另一种是O(n)的哈希表方法。哈希表方法通过一次遍历实现高效查找。

Description
Given an array of integers, find two numbers such that they add up to a specific target number.

The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are zero-based.

Example

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Language: C++

解法1:暴力搜索:O(n2)O(n2) (Runtime Error)

class Solution {
public:
    /**
     * @param numbers: An array of Integer
     * @param target: target = numbers[index1] + numbers[index2]
     * @return: [index1 + 1, index2 + 1] (index1 < index2)
     */
    vector<int> twoSum(vector<int> &numbers, int target) {
        // write your code here
        int l = numbers.size();
        int i,j;
        vector<int> a;
        for(i = 0; i < l-2; i++)
        {
            for(j = 0; j < l-1; j++)
            {
                int temp1 = numbers[i];
                int temp2 = numbers[j];
                if(temp1 + temp2 == target)
                {
                    a[0] = i;
                    a[1] = j;
                    return a;
                }
            }
        }
    }
};
  • 取vector变量的长度时,用.size(),如果是取数组的长度,用sizeof(array)/sizeof(array[0])
  • 由于返回的是容器,所以要在函数里面声明vector:vector<int> a; 无需指明长度
  • C++声明数组的方法是:int *a = new int[3];
  • 这个方法算法复杂度是O(n^2),Runtime Error

解法2:哈希表:O(n)O(n) (Accepted)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int,int> hash;//声明一个关键字key是int,value是int的类型
        vector<int> result;//声明一个容器,用于存储结果,并返回
        for(int i = 0; i < nums.size(); i++)
        {
            int numbertofind = target - nums[i];
            if(hash.find(numbertofind)!=hash.end())//哈希表里找到numbertofind
            {
                result.push_back(hash[numbertofind]);//把该key的value(桶号)push到result里面
                result.push_back(i);//再把i push到result里面
                return result;
            }
            hash[nums[i]]=i; //哈希表为空或哈希表里无numbertofind,把它存储到哈希表里,把关键字nums[i]存在i号桶里                    
        }
        return result;
    }
};

方法相同,思路相同,也是用map容器类(算法课代码)

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target){
        unordered_map<int,int> record;
        for(int i = 0; i<nums.size();i++){
            int complement = target - nums[i];
            if(record.find(complement)!=record.end()){//find complement
                res[2] = {i, record[complement]};
                return vector<int> (res, res+2);//注意这种使用方法
            }
            else
            record[nums[i]] = i;
        }
        throw invalid_argument("Couldn't find two numbers!");
    }
};

算法细节:
Time: O(n)O(n) 因为底层是哈希表,所以find方法O(1)O(1)级别的
Space:O(n)O(n) 因为使用了一个record

  • 因为没有要求顺序性,所以采用unordered_map(底层是哈希表处理插入、删除、查找)即可
  • 不能用set的原因是,set中不允许存储重复的元素,而我们要找的两个数很有可能是同样的数。(如4=2+2)
  • 由于C++中,容器类具有相同的接口,因此有类似vector<int>(res,res+2);的用法。
  • 为了避免一次性把所有数存入map的时候,重复的两个数,新的数的下标覆盖旧的数,先判断遍历里到某个元素时,map中是否存有target-这个元素,也就是这个元素的complement,如果有,则可以直接返回,如果没有,再把这个数作为key,它的索引作为它的value存入map中。这样,假如答案就是两个相同的数,在新的数覆盖旧的数之前,他们就已经都存起来并返回了,如果这两个相同的数是答案之一,也没关系,因为题目说不要求索引的顺序,所以覆盖了之后这个答案之一的这个数还是存在的。(e.g.: [2,3,2,4,6], target = 8, 第二个2的索引把第一个2的索引覆盖了,没关系,因为map中还是有2的索引,由于索引从0开始,故最终返回[2,4])
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值