Leetcode梦开始的地方--两数相加

LeetCode 梦开始的地方 —— 两数之和

1. 前言

对于很多程序员来说,LeetCode 是学习算法和数据结构的重要起点。而“两数之和”这道题目,作为 LeetCode 上的经典入门题目之一,对于理解哈希表的应用以及如何高效地解决问题有着重要的意义。本文将带你从零开始,逐步理解并实现这道题目的解决方案。

2. 题目描述

题目来源: LeetCode - 两数之和

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

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

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

示例 1:

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

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会有一个有效答案

3. 解题思路

方法一:暴力法

最直接的方法是使用双重循环遍历数组中的所有元素组合,找到满足条件的一对数值。这种方法的时间复杂度为 O(n^2),效率较低。

方法二:哈希表

更高效的解决方案是使用哈希表(字典)。我们可以通过遍历数组一次来查找目标值。对于每个元素 nums[i],我们检查 target - nums[i] 是否已经在哈希表中。如果存在,则找到了一对解;如果不存在,则将 nums[i] 存入哈希表中。

这种方法的时间复杂度为 O(n),空间复杂度也为 O(n)。

4. 代码实现

方法一:暴力法

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        int n = nums.size();  // 获取 nums 数组的长度
        for (int i = 0; i < n; ++i) {  // 第一层循环,遍历 nums 数组
            for (int j = i + 1; j < n; ++j) {  // 第二层循环,从 i+1 开始遍历,避免重复检查
                if (nums[i] + nums[j] == target) {  // 检查当前两个数之和是否等于目标值
                    return {i, j};  // 如果等于目标值,返回这两个数的索引
                }
            }
        }
        return {};  // 如果没有找到符合条件的两个数,返回空的 vector
    }
};
  1. 定义类 Solution:

    class Solution {
    

    这行代码定义了一个名为 Solution 的类。这是 LeetCode 中常见的做法,用于组织解题代码。

  2. 声明成员函数 twoSum:

    public:
        vector<int> twoSum(vector<int>& nums, int target) {
    

    这是一个公开的成员函数 twoSum,它接受一个整数向量 nums 的引用和一个整数 target 作为参数,并返回一个包含两个整数的向量。这里的 nums 是问题描述中的整数数组,target 是目标值。

  3. 获取数组长度:

        int n = nums.size();
    

    这行代码获取了 nums 向量的大小,并将其存储在整数变量 n 中。

  4. 第一层循环:

        for (int i = 0; i < n; ++i) {
    

    这是第一层循环,用于遍历整个 nums 向量。变量 i 作为索引从 0 开始递增。

  5. 第二层循环:

            for (int j = i + 1; j < n; ++j) {
    

    这是第二层循环,它从 i + 1 开始,直到 n。这样可以确保不会重复检查相同的元素对。

  6. 检查两数之和:

                if (nums[i] + nums[j] == target) {
    

    这行代码检查当前的 nums[i]nums[j] 之和是否等于 target

  7. 返回索引:

                    return {i, j};
    

    如果找到匹配的元素对,就立即返回包含这两个索引的向量 {i, j}

  8. 结束第二层循环:

                }
            }
    
  9. 结束第一层循环:

        }
    
  10. 如果没有找到匹配的元素对:

           return {};
    //如果遍历完所有的可能组合都没有找到匹配的元素对,那么返回一个空的向量。
    
    

这段代码实现了暴力法来解决“两数之和”问题,其时间复杂度为 O(n^2)。虽然这种方法不是最优的,但它简单直观,易于理解。

方法二:哈希表

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashtable;  // 创建一个无序哈希表来存储数值及其索引
        for (int i = 0; i < nums.size(); ++i) {  // 遍历 nums 向量
            auto it = hashtable.find(target - nums[i]);  // 查找哈希表中是否存在 target - nums[i]
            if (it != hashtable.end()) {  // 如果找到了对应的键
                return {it->second, i};  // 返回对应的索引对
            }
            hashtable[nums[i]] = i;  // 将当前元素 nums[i] 和它的索引 i 存入哈希表
        }
        return {};  // 如果没有找到解,返回空向量
    }
};
  1. 定义类 Solution:

    class Solution {
    

    这行代码定义了一个名为 Solution 的类。这是 LeetCode 中常见的做法,用于组织解题代码。

  2. 声明成员函数 twoSum:

    public:
        vector<int> twoSum(vector<int>& nums, int target) {
    

    这是一个公开的成员函数 twoSum,它接受一个整数向量 nums 的引用和一个整数 target 作为参数,并返回一个包含两个整数的向量。这里的 nums 是问题描述中的整数数组,target 是目标值。

  3. 创建哈希表:

        unordered_map<int, int> hashtable;
    

    这行代码创建了一个 unordered_map,用来存储每个元素的值及其在数组中的索引。unordered_map 是 C++ 标准库中的容器,提供了类似哈希表的数据结构。

  4. 遍历数组:

        for (int i = 0; i < nums.size(); ++i) {
    

    这是循环,用于遍历整个 nums 向量。变量 i 作为索引从 0 开始递增。

  5. 查找补数:

            auto it = hashtable.find(target - nums[i]);
    

    这行代码尝试在哈希表中查找 target - nums[i]find 函数返回一个迭代器,指向哈希表中对应的键,如果键不存在则返回 end()

  6. 检查是否找到补数:

            if (it != hashtable.end()) {
    

    这行代码检查 it 是否不等于 hashtable.end(),即判断 target - nums[i] 是否存在于哈希表中。

  7. 返回索引对:

                return {it->second, i};
    

    如果找到了匹配的元素,就立即返回包含两个索引的向量 {it->second, i}。这里 it->secondtarget - nums[i] 对应的索引。

  8. 更新哈希表:

            hashtable[nums[i]] = i;
    

    如果没有找到匹配的元素,则将当前元素 nums[i] 和它的索引 i 存入哈希表中,以便后续的查找。

  9. 结束循环:

        }
    
  10. 如果没有找到匹配的元素对:

           return {};
    

如果遍历完所有的元素都没有找到匹配的元素对,那么返回一个空的向量。

这段代码实现了使用哈希表来解决“两数之和”问题,其时间复杂度为 O(n),空间复杂度同样为 O(n)。这种方法比暴力法更高效,因为它只需要遍历一次数组。

5. 测试结果

运行上述代码后,我们可以得到如下输出:

Indices: [0, 1]

这与题目要求的结果一致。

6. 总结

通过解决“两数之和”这个问题,我们不仅学会了如何利用哈希表来提高算法的效率,还掌握了处理数组问题的基本技巧。这对于后续更复杂的算法问题非常有帮助。希望这篇博客能帮助你更好地理解和掌握这道经典的 LeetCode 题目。


  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FightingLod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值