javaScript 结构算法刷题 hash表

基础随想

hash表构造的三种方式

数组,map,set
(有空再写)

有效字母异位

leetcode 242
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。
注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
输入: s = “anagram”, t = “nagaram”
输出: true

var isAnagram = function(s, t) {
    if(s.length != t.length) return false
    // 创建一个字典存储,这里用数组
    const resSet = new Array(26).fill(0)
    // 定义a的基准
    const base = "a".charCodeAt()
    for(const i of s){
    	// 让s中的字母在对应的索引位置上值加1
        resSet[i.charCodeAt()-base]++
    }
    for(const i of t){
    	// 判断逻辑:如果t字符串寻到一个为0的位置,意味着t中出现了某个新的字母,直接return false
        if(!resSet[i.charCodeAt()-base]) return false
        resSet[i.charCodeAt()-base]--
    }
    return true
};

tips
charCodeAt() 方法可返回指定位置的字符的 Unicode 编码,返回值是 0 - 65535 之间的整数,表示给定索引处的 UTF-16 代码单元。
字符串中第一个字符的位置为 0, 第二个字符位置为 1,以此类推。

相关题目

leetcode383
给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。
输入:ransomNote = “aa”, magazine = “ab”
输出:false
输入:ransomNote = “aa”, magazine = “aab”
输出:true

var canConstruct = function(ransomNote, magazine) {
    const resSet = new Array(26).fill(0)
    const base = "a".charCodeAt()
    // 表直接用26个,ransom先加,magazine后减(m还要长),减到负数无所谓,后面按0判断
    for(const i of ransomNote){
        resSet[i.charCodeAt() - base]++
    }
    for(const i of magazine){
        resSet[i.charCodeAt() - base]--
    }
    for(let i=0;i<resSet.length;i++){
        if(resSet[i]>0){
            return false
        }
    }
    return true
};

leetcode 49
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的字母得到的一个新单词,所有源单词中的字母通常恰好只用一次
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]

var groupAnagrams = function(strs) {
    let res = []
    let map = new Map()
    for(let i=0;i<strs.length;i++){
        // 输入数组中的每个单词,进行单独拆分
        let k = strs[i].split('').sort().join('')
        // 如果为实例1,则i=0时,k=aet
        if(map.has(k)){
            map.get(k).push(strs[i])
        }else{
            map.set(k,[strs[i]])
        }
    }
    map.forEach((val,key)=>{
        res.push(val)
    })
    return res
};

tips
打印一下map

arr = ["the","been","eben","eebn","tah"]
Map(3) {'eht' => Array(1), 'been' => Array(3), 'aht' => Array(1)}
[[Entries]]
	0: {"eht" => Array(1)}
		key: "eht"
		value: ['the']
	1: {"been" => Array(3)}
		key: "been"
		value: (3) ['been', 'eben', 'eebn']
	2: {"aht" => Array(1)}
		key: "aht"
		value: ['ath']
	size: 3
[[Prototype]]: Map

leetcode 438
给定两个字符串 s 和 p,找到 s 中所有 p 的 异位词 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。

输入: s = “cbaebabacd”, p = “abc”
输出: [0,6]
解释:
起始索引等于 0 的子串是 “cba”, 它是 “abc” 的异位词。
起始索引等于 6 的子串是 “bac”, 它是 “abc” 的异位词。

var findAnagrams = function (s, p) {
    const pLen = p.length
    const res = [] // 返回值
    const map = new Map() // 存储 p 的字符
    for (let item of p) {
        map.set(item, map.get(item) ? map.get(item) + 1 : 1)
    }
    // 存储窗口里的字符情况
    const window = new Map()
    let valid = 0 // 有效字符个数

    for (let i = 0; i < s.length; i++) {
        const right = s[i]
        // 向右扩展
        window.set(right, window.get(right) ? window.get(right) + 1 : 1)
        // 扩展的节点值是否满足有效字符
        if (window.get(right) === map.get(right)) {
            valid++
        }
        if (i >= pLen) {
            // 移动窗口 -- 超出之后,收缩回来, 这是 pLen 长度的固定窗口
            const left = s[i - pLen]
            // 原本是匹配的,现在移出去了,肯定就不匹配了
            if (window.get(left) === map.get(left)) {
                valid--
            }
            window.set(left, window.get(left) - 1)
        }
        // 如果有效字符数量和存储 p 的map 的数量一致,则当前窗口的首字符保存起来
        if (valid === map.size) {
            res.push(i - pLen+1)
        }
    }
    return res
};

// 别人的答案,我没写

两个数组的交集

leetcode349
输入:nums1 = [1,2,2,1], nums2 = [2,2]
输出:[2]

var intersection = function(nums1, nums2) {
    // let set = new Set(nums2)
    // return [...new Set(nums1)].filter((val)=>set.has(val))

    let nums1Set = new Set(nums1)
    let res = [] 
    for(let i=0;i<nums2.length; i++){
        let temp = nums2[i]
        if(nums1Set.has(temp)){
           res.push(temp)
        }
    }
    res = new Set(res)
    // Array.from 转换成数组  
    return Array.from(res)
};

leetcode350

    const res = []
    nums2.forEach((item) => {
        const index = nums1.indexOf(item)
        if (index !== -1){
            res.push(item);
            nums1[index] = null;
        }
    })
    return res;

快乐数

leetcode202

难点,个人认为是怎么给那个表达式搞出来

var getSum = function(n){
    let sum = 0
    while(n){
        sum = sum + (n % 10) ** 2
        n = Math.floor(n/10)
    }
    return sum
}
var isHappy = function(n) {
    let set = new Set()
    while(n != 1 && !set.has(n) ){
        set.add(n)
        n = getSum(n)
    }
    return n == 1
};

两数之和

leetcode1

	let map = new Map()

    for(let i=0; i<nums.length; i++){
        let otherNum = target - nums[i]
        if(map.has(otherNum)){
            return [map.get(otherNum),i]
        }
        map.set(nums[i],i)
    }

四数相加

leetcode454
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
输入:nums1 = [1,2], nums2 = [-2,-1], nums3 = [-1,2], nums4 = [0,2]
输出:2
解释:
两个元组如下:
(0, 0, 0, 1) -> nums1[0] + nums2[0] + nums3[0] + nums4[1] = 1 + (-2) + (-1) + 2 = 0
(1, 1, 0, 0) -> nums1[1] + nums2[1] + nums3[0] + nums4[0] = 2 + (-1) + (-1) + 0 = 0

var fourSumCount = function(nums1, nums2, nums3, nums4) {
    let map = new Map()
    let n = nums1.length
    let sum1 = 0, sum2 = 0, valid = 0, search = 0

    for(let i=0; i<n; i++){
        for(let j=0; j<n; j++){
            sum1 = nums1[i] + nums2[j]
            map.set(sum1, map.has(sum1) ? map.get(sum1)+1 : 1)
        }
    }
    for(let i=0; i<n; i++){
        for(let j=0; j<n; j++){
            sum2 = nums3[i] + nums4[j]
            search = -sum2
            if(map.has(search)){
                valid = map.get(search) + valid // 不是自增1,想清楚
            }
        }
    }
    return valid
};

tips
视频里面讲的非常清楚了,数组1和2循环相加然后存字典,3和4加去字典里面找,为数不多看一半视频,写出来改一次过的

课程来自代码随想录

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值