前言
最近在刷题准备秋招,自己也总结了一些leetcode题目的JS解法,刷题我是看大佬的题解,这里只是简单梳理下思路,想看详细题解的可以进到对应的题目里面去看,每道题我都贴上对应的leetcode地址,这一期是哈希表的相关题目,后面会持续更新,感兴趣可以关注一下!
存在重复元素
简-存在重复元素-217
使用set判断是否有重复元素
/**
* @param {number[]} nums
* @return {boolean}
*/
var containsDuplicate = function(nums) {
const set = new Set()
for(let num of nums){
if(set.has(num)){
return true
}
set.add(num)
}
return false
};
简-存在重复元素2-219
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
需要用到下标,所以使用map进行存储
/**
* @param {number[]} nums
* @param {number} k
* @return {boolean}
*/
var containsNearbyDuplicate = function(nums, k) {
const map=new Map()
for(let i=0;i<nums.length;i++){
// map中存在这个值,且两个相等值的下标差<k
if(map.has(nums[i]) && (i-map.get(nums[i])<=k)){
return true
}else{
map.set(nums[i],i)
}
}
return false
};
简-扑克牌中的顺子-剑指o61
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:
方法1:set+遍历
- 通过set判断是否有重复牌
- 同时通过两个变量来储存最小最大值
/**
* @param {number[]} nums
* @return {boolean}
*/
var isStraight = function(nums) {
const set = new Set()
let max=0,min=14
for(let i=0;i<nums.length;i++){
// 遇到大小王则跳过
if(nums[i] === 0) continue
max=Math.max(max,nums[i])
min=Math.min(min,nums[i])
// 若有重复,提前返回false
if(set.has(nums[i])) return false
set.add(nums[i])
}
// 最大牌 - 最小牌 < 5 则可构成顺子
return max-min<5
};
方法2: 排序+遍历
- 将数组进行排序,最大值就为最后一个
- 通过一个变量来记录大小王的数量,最小值即为nums[joker]
/**
* @param {number[]} nums
* @return {boolean}
*/
var isStraight = function(nums) {
// 记录大小王数量
let joker = 0
// 排序
nums=nums.sort(function(a,b){
return a-b
})
for(let i=0;i<nums.length;i++){
// 遇到大小王
if(nums[i] === 0) joker++
// 若有重复,提前返回false
else if(nums[i] == nums[i+1]) return false
}
// 最大牌 - 最小牌 < 5 则可构成顺子
return nums[4] - nums[joker]<5
};
简-第一个只出现一次的字符-剑指o50
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
思路:使用哈希表记录每一个数的情况,未重复的标记为true,最后再遍历一遍哈希表,输出第一个为true的数
/**
* @param {string} s
* @return {character}
*/
var firstUniqChar = function(s) {
if(s.length==0){
return ' '
}
const map = new Map()
// 记录每个字符的情况,未重复的标记为true
for(let item of s){
map.set(item,!map.has(item))
}
// 遍历哈希表,返回第一个为true的元素
for(let m of map){
if(m[1]){
return m[0]
}
}
return ' '
};
简-两个数组的交集-349
思路:使用set存储num2,再对num1中元素进行验证
/**
* @param {number[]} nums1
* @param {number[]} nums2
* @return {number[]}
*/
var intersection = function(nums1, nums2) {
const result = new Set()
const set = new Set(nums2)//数组转set
for(num of nums1){
// 数组搜索值,复杂度O(n)
// Set Map -.has 复杂度O(1)
// 如果有交集
if(set.has(num)){
result.add(num)
}
}
return Array.from(result)
};
中-重复的DNA序列-187
思路-哈希表:
使用哈希表统计每个字符串的出现次数,返回大于2的
/**
* @param {string} s
* @return {string[]}
*/
var findRepeatedDnaSequences = function(s) {
const map = new Map()
const result = []
for(let i=0;i+10<=s.length;i++){
const dna = s.substring(i,i+10)
if(map.get(dna)===undefined){
map.set(dna,1)
}else if(map.get(dna) === 1){
map.set(dna,2)
result.push(dna)
}else{
map.set(dna,map.get(dna)+1)
}
}
return result
};
思路-set
这道题可以不使用哈希表,只用set存储判断是否重复就行
/**
* @param {string} s
* @return {string[]}
*/
var findRepeatedDnaSequences = function(s) {
const set = new Set()
const result = new Set()
for(let i=0;i+10<=s.length;i++){
const dna = s.substring(i,i+10)
if(set.has(dna)){
result.add(dna)
}else{
set.add(dna)
}
}
return Array.from(result)
};
简-有效的字母异位词-242
思路:
- 如果两个数组长度不一致,则返回false
- 创建一个map,用来存储每个字符出现的次数
- 对于第一个单词的每个字母(即s[i]),在map里出现的次数+1
- 对于第二个单词的每个字母(即t[i]),在map里出现的次数-1
- 遍历完成后,检查map里的每一个字母的出现次数是不是0,如果有一个非0的字母,则返回false,否则返回true
/**
* @param {string} s
* @param {string} t
* @return {boolean}
*/
var isAnagram = function(s, t) {
if(s.length!==t.length){
return false
}
const map = new Map()
for(let i=0;i<s.length;i++){
if(map.has(s[i])){
map.set(s[i],map.get(s[i])+1)
}else{
map.set(s[i],1)
}
if(map.has(t[i])){
map.set(t[i],map.get(t[i])-1)
}else{
map.set(t[i],-1)
}
}
for(const letter of map){
if(letter[1]!==0){
return false
}
}
return true
};
中-字母异位词分组-49
将组合单词的字母相同的排在一起
思路
- 检查是否为空数组
- 建立一个长度为26的数组,起始值为0
- 遍历所有的字符串,将字母的出现频率放到数组的对应位置里(利用ascil码)
- 遍历数组,按照相同字母出现频率进行分组归类(使用hashMap)
- 遍历map,将结果返回
具体代码
/**
* @param {string[]} strs
* @return {string[][]}
*/
var groupAnagrams = function(strs) {
if(strs.length === 0){
return []
}
const map=new Map()
for(const str of strs){
// 创建一个长度为26的数组,起始值为0
const characters= Array(26).fill(0)
// 遍历所有字符串,将字母的出现频率放到数组的对应位置里
for(let i=0;i<str.length;i++){
// 利用ascil码判断是哪个字母
const ascli=str.charCodeAt(i)-97
characters[ascli]++
}
// console.log('characters',characters)
const key=characters.join()//转为字符串
// console.log('key',key)
// 如果存在相同字母
if(map.has(key)){
// 分组拼接数组
// map.set(key,map.get(key).push(str))
map.set(key,[...map.get(key),str])
}else{
// 不存在相同字母则新建一个
map.set(key,[str])
}
}
const result = []
// 遍历map
for(const arr of map){
// console.log('arr',arr)
// [ '1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0', [ 'bat' ] ]
// console.log('arr[1]',arr[1])
// [ 'bat' ]
// arr[1]是value值
result.push(arr[1])
}
console.log('result',result)
return result
};
const strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
groupAnagrams(strs)
后续还有哈希表相关题目会继续补充的,欢迎在评论区交流