算法练习day5

71 阅读3分钟

一、哈希表理论基础

哈希表是根据关键码的值而直接进行访问的数据结构

哈希函数:通过特殊的编码方式把关键码转为可以映射到哈希表的索引

哈希碰撞:不同的关键码映射到同一个索引位置

拉链法: 当哈希函数得到的索引位置相同发生冲突,冲突的元素存储在链表中

拉链法就是要选择合适的哈希表大小,既不会因为空值而浪费空间,也不会因为链表太长使查找时间太长

线性探测法:保证哈希表长度大于数据长度

只要需要快速判断一个元素是否出现在集合里,就要考虑哈希法

二、有效的字母异位词

问题要点

字母异位词都是字母,可以把字母映射到数组的索引,统计字符串中字符出现的次数,然后判断另一个字符串是否满足要求时,遍历求减,最终数组中每个元素为0,即为字母异位词

/**
 * @param {string} s
 * @param {string} t
 * @return {boolean}
 */
var isAnagram = function(s, t) {
    if(s.length !== t.length) {
        return false
    }
    let arr = new Array(26).fill(0)
    let base = 'a'.charCodeAt()
    for(let i of s) {
        arr[i.charCodeAt() - base]++
    }
    for(let i of t) {
        if(!arr[i.charCodeAt() - base]) {
            return false
        }
        arr[i.charCodeAt() - base]--
    }
    return true
};

三、两个数组的交集

问题要点

hash表方法:通过Set存储数组元素,遍历另一个数组判断,最终的结果需要去重

双指针方法:先把两个数组排序,然后用两个指针分别指向数组的起点,如果相等,同时移动指针,如果不同,分别移动(小的移动)

哈希法

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
    if(nums1.length < nums2.length) {
        [nums1, nums2] = [nums2, nums1]
    }
    let set = new Set(nums1)
    let res = new Set()
    for(let item of nums2) {
        if(set.has(item)) {
            res.add(item)
        }
    }
    return Array.from(res)
    
};

双指针法

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var intersection = function(nums1, nums2) {
    nums1.sort((x, y) => x - y)
    nums2.sort((x, y) => x - y)
    let index1 = 0
    let index2 = 0
    let res = new Set()
    while(index1 < nums1.length && index2 < nums2.length) {
        if(nums1[index1] === nums2[index2]) {
            res.add(nums1[index1])
            index1++
            index2++
        } else if(nums1[index1] < nums2[index2]) {
            index1++
        } else {
            index2++
        }
    }
    return Array.from(res)
};

四、快乐数

问题要点

需要一个哈希表来存储计算结果,如果已经出现过,则证明不是快乐数,求和可以使用如下两种,reduce求和或者获取余数求和

/**
 * @param {number} n
 * @return {boolean}
 */
var isHappy = function(n) {
    let set = new Set()
    while( n !== 1 && !set.has(n)) {
        set.add(n)
        n = getSum(n)
    }
    return n === 1

}; 

function getSum(n) {
    // let sum = 0
    // while(n) {
    //     sum += (n % 10) ** 2
    //     n = Math.floor(n / 10)
    // }
    // return sum
    return String(n).split('').reduce((sum, cur) => {
        return sum + cur ** 2
    }, 0)
}

五、两数之和

问题要点

哈希表法:使用哈希表记录数组元素,如果能够找到与target的差值,则直接返回结果,否则添加该元素进入哈希表

/**
 * 哈希表方法
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let map = new Map();
    for(let i = 0; i < nums.length; i++) {
        if(map.has(target - nums[i])) {
            return [map.get(target - nums[i]), i]
        }
        map.set(nums[i], i)
    }
    return [-1, -1]
};