LeetCode 热题 HOT 100(00,两数之和)

LeetCode 热题 HOT 100(00,两数之和)

不够优秀,发量尚多,千锤百炼,方可成佛。

算法的重要性不言而喻,无论你是研究者,还是最近比较火热的IT 打工人,都理应需要一定的算法能力,这也是面试的必备环节,算法功底的展示往往能让面试官眼前一亮,这也是在大多数竞争者中脱颖而出的重要影响因素。

然而往往大多数人比较注重自身的实操能力,着重于对功能的实现,却忽视了对算法能力的提高。有的时候采用不同的算法来解决同一个问题,运行效率相差还是挺大的,毕竟我们最终还是需要站在客户的角度思考问题嘛,能给用户带来更加极致的体验当然再好不过了。

万法皆空,因果不空。Taoye之前也不怎么情愿花费太多的时间放在算法上,算法功底也是相当的薄弱。这不,进入到了一个新的学习阶段,面对导师的各种“严刑拷打”和与身边人的对比,才意识到自己“菜”的事实。

步入11月,也开学一个多月了,所以想开始记录下刷算法题的过程,也算是对自己的一个督促。初步的目标是一到两天更新一期,每周至少更新四期。

题目:两数之和

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

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

思路

这是LeetCode 热题 HOT 100中的第一道题,难度级别属于简单,也是每一位刷题er的入门必经之题,它的地位就等同于英语单词表中的abandon,算法记录的第一天就拿它开刀吧。

按照对这道题的正常思维,直接通过两层循环、一次判断就能完成任务,也就是我们常常提到的暴力解题,相关Python代码如下:

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        # 两层循环
        for index_1, num_1 in enumerate(nums):
            for index_2, num_2 in enumerate(nums):
                # 一次判断
                if (num_1 + num_2) == target and index_1 != index_2:
                    return [index_1, index_2]
        return []

但是,要想有效提高自己的算法能力,还是有必要培养自己的“不正常”思维的。毫无疑问,上述暴力破解自然能够满足题意的要求,但在我们的业务功能已经全部实现的情况下,就不得不考虑代码的执行效率问题了,这也就凸显出了算法的重要性。

暴力解题的时间复杂度为,空间复杂度为。但我们可以通过哈希表(key-value键值对)来降低算法的时间复杂度。

对于遍历的每一个,我们都计算其对应的的值,判断值是否在哈希表中,如果在的话说明已经匹配成功,直接返回值对应的索引。反之,我们需要将当前遍历的添加到哈希表中,x列表中所对应的索引。

如此一来,最多只需要遍历一次列表即可查找到目标值的索引,其时间复杂度为,空间复杂度为。相对于暴力解题来讲,采用的是以空间换时间的策略。

在计算机发展初期,内存是极为奢侈的,内存的使用都是要经过慎重考虑的。而在今日,曾今的内存问题已经不再是问题了,有的时候,站在客户的角度来讲,我们通常会情愿采用以空间换时间的策略。

代码实现

  • Python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = dict()
        for index, num in enumerate(nums):
            if (target - num) in hashtable:     # 补集在哈希表中,直接返回目标索引
                return [hashtable.get(target - num), index]
            hashtable[num] = index              # 补集不在哈希表中,添加到hashtable
        return []
  • C++

官方

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<intint> hashtable;
        for (int i = 0; i < nums.size(); ++i) {
            auto it = hashtable.find(target - nums[i]);     // find查询关键字,没找到则返回end迭代器
            if (it != hashtable.end()) {                    // 如果找到了目标关键字
                return {it->second, i};                     // 返回索引
            }
            hashtable[nums[i]] = i;                         // 没找到,则将关键字添加到hashtable
        }
        return {};
    }
};

在C++中,通过hashtable作为底层实现的主要有两个容器

  • unordered_set,就是一个单类型数据的set集合,内部的元素不能重复,比如名字set集合,name_set={"taoye", "taotao"}
  • unordered_map,一个key-value键值对型的容器,比如id、姓名类型的map,info_map={1: "taoye", 2: "taotao"}
// 在unordered_map中,find用于进行关键字的查询,找到则返回指向关键字的迭代器,否则返回指向end的迭代器
iterator find (const key_type& k);

我是Taoye,研究生在读。爱专研,爱分享,热衷于各种技术,学习之余喜欢下象棋、听音乐、聊动漫,希望借此一亩三分地记录自己的成长过程以及生活点滴,也希望能结实更多志同道合的圈内朋友,更多内容欢迎来访微信公主号:玩世不恭的Coder

推荐阅读:

Taoye渗透到一家黑平台总部,背后的真相细思极恐
《大话数据库》-SQL语句执行时,底层究竟做了什么小动作?
那些年,我们玩过的Git,真香
基于Ubuntu+Python+Tensorflow+Jupyter notebook搭建深度学习环境
网络爬虫之页面花式解析
手握手带你了解Docker容器技术
一文详解Hexo+Github小白建站
​打开ElasticSearch、kibana、logstash的正确方式

posted @ 2020-11-02 16:11  玩世不恭的Coder  阅读(362)  评论(0编辑  收藏  举报