1 两数之和(Two Sum)
题目
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]
解答
暴力遍历法
Runtime: 172 ms, faster than 16.41% of JavaScript online submissions for Two Sum.
Memory Usage: 34.7 MB, less than 66.18% of JavaScript online submissions for Two Sum.
哈希表
哈希表是一种介于数组和链表之间的数据结构
数组
数组就是一个位置一个坑,需要数据基本整齐的。这样查找很方便,有key就能找到value,用value找key稍微麻烦点。数据的增添和删除上就更麻烦了,删了第一个,整个数组都要一个个往前挪一位。
链表
每个链表元素只记得怎么找到后面那个元素。类似于做广播操的队列,每个人只需要记住前面那个人是谁,队伍就能排起来了。 这样数据的增删就很方便,只需要换一个元素记就行了。但数据的查询就很麻烦,只能从头往后一个个查,直到找到。
哈希表
哈希表就是粘在一个个数组位置上的链表。
通过哈希函数,把key换算成数组的位置,然后放入数组。如果有冲突,就用链表结构,粘在这个数组位置后面。
要找的时候,通过哈希函数算出元素所在数组的位置,以此进入链表,再一个个摸到想要的元素。这比从头一个个摸过来要快得多。 要删改的时候,也是算出数组位置进入,直接修改前后两个链表的指向即可。这比数组一个个挪位置也要快得多。
换言之,哈希表是在用空间换时间。
那么哈希函数是怎么计算出数组的位置的呢? 最简单的方式可以使用取模的方式来确定下标。数组长度多大,就取多大数的模(最好是素数)
Runtime: 56 ms, faster than 92.05% of JavaScript online submissions for Two Sum. Memory Usage: 36.1 MB, less than 13.21% of JavaScript online submissions for Two Sum.
这里有个有趣的思路。题目中是两数相加等于targetnums[i] + nums[j] == target
,而这里是算出距离target还差多少,然后找那个差距的值const result = target - nums[i]; arrMap.has(result)
一遍哈希表:
Runtime: 52 ms, faster than 96.57% of JavaScript online submissions for Two Sum.
Memory Usage: 35.1 MB, less than 33.80% of JavaScript online submissions for Two Sum.
感觉哈希表和对象很像,那如果用对象改写呢?
Runtime: 72 ms, faster than 61.90% of JavaScript online submissions for Two Sum.
Memory Usage: 36.3 MB, less than 10.22% of JavaScript online submissions for Two Sum.
感觉和map差不多,稍逊一筹。
那么Map和Object的区别是啥呢?
Object对象有原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
除非我们使用Object.create(null)创建一个没有原型的对象;
在Object对象中, 只能把String和Symbol作为key值
但是在Map中,key值可以是任何基本类型(String, Number, Boolean, undefined, NaN….),或者对象(Map, Set, Object, Function , Symbol , null….);
Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。 【比如map的key是一个引用,那么它的操作,是直接把引用内容复制到新的地方,而obj则是转成string之后再贴到新的地方】
Map中不能有重复的key
通过Map中的size属性, 可以很方便地获取到Map长度, 要获取Object的长度, 没有直接的方法;
lint
的规范是不让用obj.hasOwnProperty
的。
在大型系统中,如果要实例化一个object
,一般是用Object.creat(null)
,这样object
就不会继承任何的方法。我们在prototype
写方法的时候也不会污染原有的Object
原型。毕竟object
是所有人的爹,这样做会更加安全吧
Last updated
Was this helpful?