力扣最热一百题——1.两数之和

目录

吐槽

题目链接: 1. 两数之和 - 力扣(LeetCode)

题目

示例

提示

解法一:暴力枚举

思路

代码实现

解法二:哈希表

什么是哈希表?

哈希表可以解决什么类型的问题?

思路

代码实现

结论


吐槽

        这个暑假因为真的忘记把我的算法书带回来了,这样导致的结果就是我刷算法题比较难受,那我就把力扣最热一百题在这个暑假全部更新完就算成功吧嘿嘿。然后我可能会再更新一点Java的知识例如spring等的,当时学习的时候就没有笔记,现在也忘记的差不多了,是时候回顾一下了。

        话不多说,我们来到力扣最热一百题的第一题吧。


题目链接: 1. 两数之和 - 力扣(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
  • 只会存在一个有效答案

进阶:你可以想出一个时间复杂度小于 O(n^{2}) 的算法吗?

这里就是我们提到的哈希表的解法了。


解法一:暴力枚举

思路

        对于暴力枚举的题目来说,思路其实都是非常的清晰的, 我们只需要遍历所有的情况,然后判断符合题意的情况即可。

        对于具体的这道题目来说我们需要返回的是一个数组之中两个元素加和为一个目标数值的数的对应两个元素的下标。那么其实问题大家都能想到非常简单,我们只需要找到所有的两个数的组合然后判断哪一个组合满足上述的条件即可。

        当然了,代码之中还是存在一些细节,我在代码中写了非常详细的注释。


代码实现

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 获取到数组的长度
        int len = nums.length;
        // 进入暴力逻辑,遍历出所有的两数的可能
        // 这里不要包括最后一位
        // 因为如果包括了最后一位的话,就会导致问题
        // 因为题目给出同时不能同时出现两个同一元素(索引同一)
        // 不-1就会出现同一元素
        for(int i = 0; i < len - 1;i++){
            // 由于在题目中提到同一个元素不能出现两次
            // 所以排除这个i位置
            for(int j = i + 1; j < len;j++){
                if(nums[i] + nums[j] == target){
                    // 这里就说明找到了
                    return new int[]{i,j};
                }
                // 否则不会进入if继续寻找
            }
        }
        // 根本不会执行到这里所以直接返回两个特殊-1
        return new int[]{-1,-1};
    }
}

        怎么说呢,这个运行效率非常的low好吧,因为这里用到了两个for循环,这里的代码时间复杂度实际上是在O(n^{2}),也就是测试用例不多,不然非常的难搞。

解法二:哈希表

        在解释哈希表的解法之前我们先了解一下什么是哈希表。

什么是哈希表?

        哈希表(Hash table),也称为散列表,是一种存储数据的数据结构。它通过将键(key)映射到一个值(value)来实现高效的数据查找。哈希表使用哈希函数将键映射到一个数组的索引,然后将值存储在该索引的位置上。当需要查找一个键对应的值时,哈希表会使用相同的哈希函数计算出键的索引,然后直接查询该索引的位置,从而实现快速的查找。

        哈希表的查找、插入和删除操作的时间复杂度都是常数级别O(n),即不随数据量增加而增加,因此在大多数情况下,哈希表的性能非常高。然而,由于哈希函数的设计和冲突问题,有时候会导致性能下降(最坏情况下,查找、插入和删除操作的时间复杂度可能变为O(n),因此需要合理选择哈希函数和解决冲突的方法来确保哈希表的高效性。


哈希表可以解决什么类型的问题?

哈希表可以解决需要高效地插入、查找和删除元素的问题。那么具体来说,哈希表适用于:

  1. 查找元素:哈希表可以通过将键映射到其对应的索引位置,从而实现常数时间复杂度O(n)的查找操作。这使得哈希表非常适合存储大量数据并快速查找特定元素的场景。
  2. 去重:由于哈希表中每个键都是唯一的,因此可以轻松地使用哈希表来去除重复元素。只需将元素依次插入哈希表中,重复的元素将被自动忽略。
  3. 缓存管理:哈希表可以用作缓存数据结构,其中键是被缓存的数据的唯一标识符,值是对应的缓存数据。这样,可以快速查找缓存中是否存在特定的数据,以提高读取效率。
  4. 分组和统计:哈希表可以用于将元素按照一定的规则分组,并统计每组中元素的数量。这在统计分析和数据挖掘等领域非常常见。 总的来说,哈希表适用于需要快速存储、查找和删除元素的场景,并且通常在处理大量数据时具有优势。

所以我们这里要用到的就是查找元素。


思路

        我们只需要遍历一次每个元素,然后看在哈希表中是否存在一个元素,与当前元素相加等于target,如果有这个元素,那么我们直接返回当前元素的下标和哈希表中存储的元素的下标即可。对于没有的情况,我们将当前元素的大小和对应的下标加入到哈希表中,供其他的元素来匹配。通过这样,我们就不需要寻找两个元素的全部组合情况了。

        具体代码实现如下,有一些代码细节也给出了详细的注释。

代码实现

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 我们这里采用map集合来作为哈希表的具体实现
        // 我们这里将key设置为元素大小,value设置为元素对应的索引
        Map<Integer,Integer> map = new HashMap<>();

        for (int i = 0; i < nums.length; i++) {
            // 先判断当前元素是否和哈希表中的某一元素加起来为targe
            // 也就是是否包含一个 key = target - 当前元素
            int aim = target - nums[i];
            if (map.containsKey(aim)){
                // 包含那就返回索引
                return new int[]{i, map.get(aim)};
            }else {
                // 否则就将元素加入到map集合之中
                map.put(nums[i], i);
            }
        }
        // 不会没有答案,但是这里必须要返回所以我们就返回一个-1,-1
        return new int[]{-1,-1};
    }
}

        在看题目的最后一句话,能不能采用低于O(n^{2})的方法来解决这个问题,那么我们在采用哈希表之后其实时间复杂度也就降到了O(n)了,完美解决问题,但是没有打败百分之百的人可能是语言的问题,或者力扣在之后扩大的测试用例的大小导致后面的结果没办法超过一开始的人。


结论

        作为一道非常经典的题目,大家可以学习。暴力的思想是算法的最基础的思想。当然了最后也引入了哈希表这么一个数据结构可以作为拓展内容来了解。

  • 13
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

WenJGo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值