两数之和(Hash表)[简单]

这篇具有很好参考价值的文章主要介绍了两数之和(Hash表)[简单]。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

优质博文:IT-BLOG-CN

一、题目

给定一个整数数组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(n2)的算法吗?

二、代码

哈希表思路:
【1】先获取数组中的第一个元素,通过target - num[i] = x,直接过去x的下标,存在直接返回当前索引和查询到的索引,但需要对[3,3]=6等特殊场景进行处理。
【2】们发现这个题目属于hash表下面的,所以使用hash表来实现。可以用key保存数值,用value在保存数值所在的下标map中的存储结构为{key:数据元素,value:数组元素对应的下表}

在遍历数组的时候,只需要向map去查询是否存在target - num[i] = x中的x,如果存在,就返回value也就是下标和i,如果没有,就把目前遍历的元素放进map中,因为map存放的就是我们访问过的元素。

两数之和(Hash表)[简单],算法题,哈希算法,算法,数据结构,后端,java,面试,职场和发展

两数之和(Hash表)[简单],算法题,哈希算法,算法,数据结构,后端,java,面试,职场和发展

class Solution {
    public int[] twoSum(int[] nums, int target) {
        // 先获取数组中的第一个元素,通过 target - num[i] = x, 直接过去x的下标,存在直接返回,需要对[3,3]相同的做特殊处理。
        // 我们发现这个题目属于 hash表下面的,所以使用hash表来实现。可以用key保存数值,用value在保存数值所在的下标
        // map中的存储结构为 {key:数据元素,value:数组元素对应的下表}
        int[] res = new int[2];
        Map<Integer,Integer> map = new HashMap();
        for (int i = 0; i < nums.length; i++) {
            int x = target - nums[i];
            if (map.containsKey(x)) {
                res[0] = map.get(x);
                res[1] = i;
                return res;
            }
            map.put(nums[i], i);
        }
        return res;
    }
}

时间复杂度: O(N),其中N是数组中的元素数量。对于每一个元素x,我们可以O(1)地寻找target - x
空间复杂度: O(N),其中N是数组中的元素数量。主要为哈希表的开销。

暴力枚举: 最容易想到的方法是枚举数组中的每一个数x,寻找数组中是否存在target - x

当我们使用遍历整个数组的方式寻找target - x时,需要注意到每一个位于x之前的元素都已经和x匹配过,因此不需要再进行匹配。而每一个元素不能被使用两次,所以我们只需要在x后面的元素中寻找target - x

class Solution {
    public int[] twoSum(int[] nums, int target) {
        int n = nums.length;
        for (int i = 0; i < n; ++i) {
            for (int j = i + 1; j < n; ++j) {
                if (nums[i] + nums[j] == target) {
                    return new int[]{i, j};
                }
            }
        }
        return new int[0];
    }
}

时间复杂度: O(N^2),其中N是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
空间复杂度: O(1)

思考:
1、如果nums是有序的,是否还需要哈希表?换句话说,能否做到O(1)额外空间?
2、如果要求寻找三个数,它们的和等于target呢?

含有重复元素的两数之和(字节算法工程师面试题) :给定一个可能包含重复元素的有序数组,以及一个目标值target。计算数组中有多少对两个整数的组合满足和等于target
示例1: nums=[2,2,2,2], target= 4, ans=6
示例2: nums=[1,1,2,2,2,2,3,3], target=4, ans=10
示例3: nums=[1,1,1,1], target=4, ans=0

其实第一眼看上去倒也不难,就是一个变体的两数之和。所以刚开始的思路就是先统计每一个数出现的次数,然后再按照两数之和的方法去算,只不过算的时候要考虑两个数出现的次数相乘才是所有的组合。

但是面试官说还有更好的,让我往三数之和上想。但是我想偏了,我一直想的是在三数之和中如果当前数和前一个数相等,那么会直接跳过。这里的话应该是可以根据前一个数对答案的贡献度直接推出来当前数的贡献度的。比如[1,1,2,2,2,2,4,4]的测试用例,首先第一次计算出第一个1对结果的贡献度是2之后,指针右移,又遇到一个1,那么可以不用计算,直接加上上一次的答案,同理,第一次遇到2也是,但是由于2 = 4 - 2,所以,第二次遇到2的时候,不能直接加上上一次的答案,应该加上上一次的答案-1

import bisect
def solve(nums, target):
    ans = 0
    pre = 0
    for i, num in enumerate(nums):
        if num == target - num:
            r = bisect.bisect_right(nums, num)
            ans += (r - i) * (r - i - 1) // 2
            return ans

        if i > 0 and nums[i-1] == num:
            ans += pre
            continue
        l, r = bisect.bisect_left(nums, target - num), bisect.bisect_right(nums, target - num)
        if l < r:
            ans += r - l
            pre = r - l

    return ans

面试完又想了一下另一个思路,可以按照三数之和内层循环的思路,用两个指针分别指向首尾,
1、如果这两个数的和小于taregt,右移左指针,
2、如果大于target,左移右指针。
3、如果等于target,分情况讨论
4、如果两个数相等,可以直接计算,然后终止循环。因为数组有序,继续循环下去也没意义。
5、如果两个数不相等,分别计算出左右两个数出现的次数。然后再计算对答案的贡献度。

时间复杂度: 因为每个数最多只会遍历一次,所以是O(n)
空间复杂度: 只需要常数级的额外空间,所以是:O(1)文章来源地址https://www.toymoban.com/news/detail-807120.html

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        ans = 0
        left, right = 0, len(nums) - 1

        while left <= right:
            current_sum = nums[left] + nums[right]

            if current_sum == target:
                # 找到一组满足条件的组合
                if nums[left] == nums[right]:
                    ans += (right - left + 1) * (right - left) // 2
                    break

                # 统计左右两个数各自出现的次数
                left_num, right_num = 1, 1
                left += 1
                right -= 1
                while left <= right and nums[left] == nums[left - 1]:
                    left_num += 1
                    left += 1
                while left <= right and nums[right] == nums[right + 1]:
                    right_num += 1
                    right -= 1
                ans += left_num * right_num
            elif current_sum < target:
                left += 1
            else:
                right -= 1

        return ans

到了这里,关于两数之和(Hash表)[简单]的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • LeetCode:1. 两数之和——哈希表~

    🍎道阻且长,行则将至。🍓 🌻算法,不如说它是一种思考方式🍀 算法专栏: 👉🏻123 题目描述 :给定一个整数数组 nums 和一个整数目标值 target ,请你在该数组中找出 和为目标值 target 的那 两个 整数, 并返回它们的数组下标 。 你可以假设每种输入只会对应一个答案。

    2024年02月02日
    浏览(86)
  • 代码随想录 -- 哈希表--两数之和

    力扣hot1:两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。 示例: 给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] +

    2024年02月09日
    浏览(39)
  • 解决两数之和问题的哈希表方法

    在给定整数数组中寻找和为目标值的两个整数,并返回它们的数组下标。通过暴力枚举或哈希表方法,时间复杂度小于O(n^2)。Java和C++代码解决方案。

    2024年02月01日
    浏览(48)
  • 数据结构哈希表(散列) 之Hash

    声明: 此文章仅限于记录学习之用 , 受限于自身水平和理解能力 , 因此结论可能是不正确的. 如果您需要学习,建议参考其他文章 看了下网上一些大佬的教程, 写的云山雾绕的. 简单总结下吧. 以言简意赅为主. hash 就是把任意输入通过算法生成一个int值. 这个值就是放数据的地址

    2024年02月21日
    浏览(47)
  • 数据结构 in Golang:Hash Tables(哈希表)

    水果店的价格表: 苹果 Apple:3元 香蕉 Banana:4元 桃子 Peach:2元 梨 Pear:3元 找到一种水果的价格: 可以使用 binary search,通过名称来查找,耗时:O(logn) 如何只耗时 O(1) 来找到价格呢? Hash 函数:通过一个字符串 - 一个数值 例如: \\\"Apple\\\" - 1 \\\"Banana\\\" - 2 \\\"Peach\\\" - 7 \\\"Pear\\\" - 8 将字符

    2024年02月08日
    浏览(72)
  • day6 哈希 有效的字母异位词 两个数组的交集 快乐数 两数之和

    - day5周日休息 --- 哈希表 - 什么时候用     - 需要记录对比数据,判断数据是否在集合里面 - 哈希三种形式     1. 数组         - 记录一个数         - 已知长度,belike 26个字母         - 已知最大长度,且长度较小,belike 1 = num = 1000     2. set         - 记录一个数

    2024年02月16日
    浏览(66)
  • Java学数据结构(4)——散列表Hash table & 散列函数 & 哈希冲突

    1.散列表,key,散列函数; 2.哈希冲突的解决; 3.string中的hashCode; 查找树ADT,它允许对元素的集合进行各种操作。本章讨论散列表(hash table)ADT,不过它只支持二叉查找树所允许的一部分操作。散列表的实现常常叫作散列(hashing)。散列是一种用于以常数平均时间执行插入、删除和

    2024年02月10日
    浏览(55)
  • 力扣 | 哈希表1 | 242.有效的字母异位词,349.两个数组的交集,202.快乐数,1.两数之和

    目录 理论基础 242.有效的字母异位词 349.两个数组的交集 202.快乐数 1.两数之和 哈希表用来判断一个元素是否出现在集合里(判断一个元素是否出现过)。 牺牲空间换时间,会使用到额外的空间。 又称散列表,key-value,根据key值来访问 (数组就是简单的哈希表,但是数组的大

    2024年02月21日
    浏览(41)
  • 代码随想录 Day6 哈希表 哈希表理论基础, 242.有效的字母异位词, 349. 两个数组的交集,202. 快乐数,1. 两数之和

    yi  哈希表理论基础 哈希表是采用了牺牲空间换取时间,因为需要存储额外的数据。 需要快速判断一个元素是否出现在一个 数组中的时候就需要哈希法。 er  242.有效的字母异位词 本题一开始想到的是使用map,感觉是字母和数字的组合 问题:  1. 注意给\\\'a\\\'穿衣服 2.想到其实

    2024年03月09日
    浏览(47)
  • 力扣简单1道_两数之和

    两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。 之前做过这道

    2024年02月15日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包