备战秋招60天算法挑战,Day1

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

视频题解: https://b23.tv/g6f8fCg

LeetCode 1.两数之和

题目描述

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

举个例子:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

视频题解

视频题解

思路解析

首先暴力的方法就不说了,比较简单但是时间复杂度比较高。这里讲一种空间换时间的方法,利用hash表,提前把nums中的元素nums[i]作为hash表的key主键,nums的索引作为hash表的value值存到hash表中。

这样我们只需要遍历nums,在hash表中寻找target-nums[i],如果target-nums存在hash表中,且hash[target-nums] != i,那么就返回{i,hash[target-nums]}。如果遍历完整个nums都没有任何结果返回,就说明没有找到。

C++代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> u_map;
        int nums_len = nums.size();
        //预先生成hash表
        for (int i = 0; i < nums_len; ++i) {
            u_map[nums[i]] = i; 
        }
        for (int i = 0; i < nums_len; ++i) {
            //查询由nums所有元素生成的hash表
            if(u_map.find(target-nums[i]) != u_map.end() && u_map[target-nums[i]] != i) {
                return {i, u_map[target-nums[i]]};
            } 
        }
        return {};
    }
};

java代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> u_map = new HashMap<>();
        int nums_len = nums.length;
        // 预先生成哈希表
        for (int i = 0; i < nums_len; i++) {
            u_map.put(nums[i], i);
        }
        for (int i = 0; i < nums_len; i++) {
            // 查询由nums所有元素生成的哈希表
            if (u_map.containsKey(target - nums[i]) && u_map.get(target - nums[i]) != i) {
                return new int[]{i, u_map.get(target - nums[i])};
            }
        }
        return new int[]{};
    }
}

python代码

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        u_map = {}
        nums_len = len(nums)
        # 预先生成哈希表
        for i in range(nums_len):
            u_map[nums[i]] = i
        for i in range(nums_len):
            # 查询由nums所有元素生成的哈希表
            if target - nums[i] in u_map and u_map[target - nums[i]] != i:
                return [i, u_map[target - nums[i]]]
        return []

上面的方法我们需要预先生成hash表,这样就会遍历两次nums,那么能否只遍历一遍nums呢?对于nums[i],我们只需要把每次查询由nums中所有元素组成的hash表,修改为每次查询由nums[0]~nums[i-1]组成的hash表,其实效果是一样的。

C++代码

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> pre_map;
        int nums_len = nums.size();
        for (int i = 0; i < nums_len; ++i) {
            //查询由nums[0]~nums[i-1]组成的hash表
            if(pre_map.find(target-nums[i]) != pre_map.end()) {
                return {pre_map[target-nums[i]], i};
            } else {
                //把当前nums[i]放入hash表
                pre_map[nums[i]] = i;
            }
        }
        return {};
    }
};

java代码

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> preMap = new HashMap<>();
        int numsLen = nums.length;
        for (int i = 0; i < numsLen; i++) {
            // 查询由nums[0]~nums[i-1]组成的哈希表
            if (preMap.containsKey(target - nums[i])) {
                return new int[]{preMap.get(target - nums[i]), i};
            } else {
                // 把当前nums[i]放入哈希表
                preMap.put(nums[i], i);
            }
        }
        return new int[]{};
    }
}

python代码

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        pre_map = {}
        nums_len = len(nums)
        for i in range(nums_len):
            # 查询由nums[0]~nums[i-1]组成的哈希表
            if target - nums[i] in pre_map:
                return [pre_map[target - nums[i]], i]
            else:
                # 把当前nums[i]放入哈希表
                pre_map[nums[i]] = i
        return []

复杂度分析

时间复杂度: 只需要遍历一遍nums,每次查hash表的时间复杂度是O(1),故整体的时间复杂是O(n),其中nnums的长度。

空间复杂度: 需要借用一个hash表,其大小为nnnums的长度,所以空间复杂度为O(n)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值