Acwing.75 和为S的两个数字

题目:从n个数中找到两个数其和为target

暴力解法:

不难想到本题的一个简单的解法在于暴力求解,即用嵌套for循环遍历所有选项从而求得答案,但是这种解法的时间复杂度为O(n^2)

哈希解法:

题目分析:

分析本题可知本题的难点在于确认一个数nums后target-nums这个数的查找比较复杂,在数组中需要通过遍历去求得。也就是说本题的时间复杂度主要在于查找,那么如果我们能想到一个数据结构它能够在仅仅知道值的情况下用O(1)的复杂度去找到这个数那么本题的复杂度便会简化为O(n)。

分析到这里,不难想到一个数据结构————哈希表。哈希表的优点就是按值查找和插入的时间复杂度为O(1)。

哈希表知识补充:

哈希表的本质和使用目的:

哈希表的核心就是数组,不过数组的下标和数组的值存在一定的关系(当存储数字时,这个关系可以简单的用hash(key)一个模除去表示;若存储字符等,要先将字符进行转化,转为数字再建立关系)。

综上,哈希表的其中一个目的就是把要存储的值和其下标建立一种联系从而使得按值查找的时间复杂度大大减低,同时插入的复杂度也相当低。当然哈希表的这种做法另一个目的就是让一个比较大的空间映射到一个较小的空间。

这两个目的的本质也是一样的。正是因为想要按值查找方便所以导致存储的空间过大,导致存储空间过大从而想到哈希表的空间映射。

哈希冲突及其解决方案:

哈希表的这种处理存在的一个问题就是哈希冲突。就是两个不一样的值通过哈希函数之后可能生成相同的值,因为我们把巨大的空间转出成较小的数组空间时,不能保证每个数字都映射到数组空白处。所以这里就会产生冲突。

处理这个冲突的方式有开放寻址法和链表法。其中开放寻址法分为线性探测、二次探测、双哈希。线性探测存在一次聚集的问题,二次探测存在二次聚集的问题(二次聚集的现象不是很严重但是仍没有双哈希要好),双哈希本质就是在一个哈希函数确认数值位置的基础上再找一个哈希函数去确认这个数如果要前进的话,其步长是多少,这样子两次哈希那么出现冲突的可能性就非常的小。如果想要具体了解哈希表及哈希冲突的相关知识见知乎https://zhuanlan.zhihu.com/p/144296454。

本题具体解法分析:

回到本题,本题采用哈希表的办法来提高按值查找的速度,这就延申出新的问题,对于本题数据要如何建立哈希表。建立的方式有两种:一、在程序一开始便把所有的数放到哈希表中,那么在定位target-nums时可以直接去找。二、在查找过程中建立哈希表。先确定第一个数然后在已经建立的哈希表中去查找,找到便结束程序,没有找到则把这个数插入哈希表中。(查找建立同步进行)

cpp中有四个stl容器底层原理是哈希表,本题选用unordered_set函数,其inset方法插入,count方法按值查找(返回值为bool)

代码如下:

class Solution {

public:
    vector<int> findNumbersWithSum(vector<int>& nums, int target) {
        unordered_set<int> hash;

        for(auto x:nums){
            if(hash.count(target-x)) return {x,target-x};
            hash.insert(x);
        }

    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

十二月的猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值