今日题目:
- 242.有效字母的异同
- 349. 两个数组的交集
- 202. 快乐数
- 1. 两数之和
解题思想:
常用的三种哈希结构:数组、set、map,当我们遇到了要快速判断一个元素是否出现在集合里的时候,就可以考虑哈希法,它使用空间换取时间。
- 利用小写字母的ASCIⅡ码连续
可以不用关心具体ASCIⅡ码是多少,但是我们知道的是它们一定是连续的,利用
charCodeAt()
方法求得具体ASCIⅡ码。所以可以定义一个长为26的数组,用来统计各个字符出现的频率。也可以使用map作哈希表来统计。
- 数组去重
在349题,两个数组的交集中,很重要的一点是答案需要去重处理,所以马上想到利用Set特性进行数组去重。将一个表设置为哈希表,遍历另一个表,判断每个元素是否在哈希表中出现,如果出现了,那么就把它加入到答案数组中。
- 无限循环
202题快乐数,此题的关键就是如何出现破除无限循环并跳出。在求和的过程中,只要重复出现过之前出现过的数,我们就可以知道它必定是无限循环。所以利用哈希表来记录每个sum,当sum再次出现就可以直接return false。否则一直找到1为止。
- 合理利用map的key和value
第一题,两数之和,
梦开始的地方,写过好多遍熟悉到已经不用动脑子就可以写出来了哈哈。我们用Map来存储出现过的数字时,存储结构是{key:数据元素, value:数组元素对应下标},因为只有这样存储,我们才可以通过map.has()
快速判断某个数是否已经出现在了map中,(map.has()
方法是用来判断键是否存在,而不是值是否存在)。因为返回的是数组下标,我们再利用map.get()
获取对应数据所在的下标。
代码:
- 242.有效字母的异同
//数组实现版
var isAnagram = function(s, t) {
if(s.length !== t.length) return false
const res = new Array(26).fill(0)
const base = "a".charCodeAt()
for(const i of s){
res[i.charCodeAt()-base]++
}
for(const i of t){
if(!res[i.charCodeAt() - base]) return false
res[i.charCodeAt()-base]--
}
return true
};
//map实现版
var isAnagram = function(s, t) {
if(s.length !== t.length) return false
const map = new Map()
for(let i = 0; i<s.length; i++) {
遍历字符串s,对s操作
if(map.has(s[i])){
map.set(s[i],map.get(s[i])+1)
} else {
map.set(s[i], 1)
}
//遍历字符串t,对t操作
if(map.has(t[i])){
map.set(t[i],map.get(t[i])-1)
} else {
map.set(t[i], -1)
}
}
for(const item of map){
if(item[1] !== 0) return false
}
return true
};
- 349 . 两个数组的交集
var intersection = function(nums1, nums2) {
//nums1为长度更长的数组
if(nums1.length < nums2.length) {
const temp = nums1
nums1 = nums2
nums2 = temp
}
const set = new Set(nums1) //利用set特性给nums1去重
const res = new Set() //保存答案的set集合, 给答案集合自动去重
for(const num of nums2) {
set.has(num) && res.add(num)
}
return Array.from(res)
};
- 202 . 快乐数
var isHappy = function(n) {
const set = new Set()
//如果在循环中某个值重复出现,说明陷入了死循环,不会进入此循环,直接通过下面判断返回true
//只有在set中没有的时候,才需要进入此循环
while(n !== 1 && !set.has(n)) {
set.add(n)
n= getSum(n)
}
return n==1
};
//专门用来计算每位数的和
var getSum = function(n) {
let sum = 0
while(n) {
sum += (n%10) **2
n = Math.floor(n/10)
}
return sum
}
-
- 两数之和
var twoSum = function(nums, target) {
const map = new Map()
for(let i = 0; i<nums.length; i++) {
if(map.has(target-nums[i])){
return [map.get(target-nums[i]), i]
} else {
map.set(nums[i], i)
}
}
return []
};
总结:
不得不说代码随想录给出的题解比我自己的优美太多了…快乐数这道题虽然不难,但是在细节实现上有很多我想不到的优雅的写法:比如,循环计算的这部分代码,当此时的sum已经存在于set中时,可以无需进入while代码块,直接在最后使用n==1
来控制返回true
还是false
,while循环中只需要执行n不等于1且set中没有出现过n的逻辑。以及getSum函数,我自己一开始实现是先把它转为数组,再遍历相加,多走了一步弯路。
while(n !== 1 && !set.has(n)) {
set.add(n)
n= getSum(n)
}
return n==1