当前位置: 首页 > article >正文

力扣 Hot 100 题解 (js版)更新ing

🚩哈希表

1. 两数之和

Code:

暴力法

复杂度分析:

  • 时间复杂度: ∗ O ( N 2 ) ∗ *O(N^2)* O(N2),其中 N 是数组中的元素数量。最坏情况下数组中任意两个数都要被匹配一次。
  • 空间复杂度:O(1)。
/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    let len = nums.length
    for (let i = 0; i < len; i++) {
        for (let j = i + 1; j < len; j++) {
            if (nums[i] + nums[j] === target) {
                return [i, j]
            }
        }
    }
};

哈希表

复杂度分析:

  • 时间复杂度:O(N),其中 N 是数组中的元素数量。对于每一个元素 x,我们可以 O(1) 地寻找 target - x。
  • 空间复杂度:O(N),其中 N 是数组中的元素数量。主要为哈希表的开销。
/**
 * @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 []
};



49. 字母异位词分组

题目 “字母异位词分组” 的目标是将一组字符串按照字母异位词(即字符串由相同的字母组成,字母顺序不同)分组。

我们可以通过以下思路解决:

思路:

  1. 特征值:排序法
    • 字母异位词具有一个共同特点:它们的字母排序后会得到相同的结果。
    • 例如:"eat""tea" 排序后都是 "aet"
    • 将每个字符串的排序结果作为键,将具有相同排序结果的字符串分到同一组。
  2. 数据结构
    • 使用一个哈希表(Map),键是排序后的字符串,值是一个数组,存储具有相同特征值的字符串。
  3. 步骤
    • 遍历字符串数组,对每个字符串排序。
    • 将排序后的字符串作为键存入哈希表,值是对应的字符串数组。
    • 遍历完成后,哈希表的值即为分组结果。

Code:

复杂度分析

  1. 时间复杂度
    • 对每个字符串进行排序的时间复杂度为 O ( k log ⁡ k ) O(k \log k) O(klogk),其中 k k k 是字符串的平均长度。
    • 遍历数组的时间复杂度为 O ( n ) O(n) O(n),其中 n n n 是字符串数组的长度。
    • 总时间复杂度为 O ( n ⋅ k log ⁡ k ) O(n \cdot k \log k) O(nklogk)
  2. 空间复杂度
    • 使用了一个哈希表来存储分组结果,空间复杂度为 O ( n ⋅ k ) O(n \cdot k) O(nk),其中 n n n 是字符串数组的长度, k k k 是字符串的平均长度。
/**
 * 字母异位词分组
 * @param {string[]} strs
 * @return {string[][]}
 */
function groupAnagrams(strs) {
    const map = new Map(); // 创建一个哈希表
    for (const str of strs) {
        // 对字符串排序后作为特征值
        const sortedStr = str.split('').sort().join('');
        // 如果哈希表中没有该特征值,则初始化为一个数组
        if (!map.has(sortedStr)) {
            map.set(sortedStr, []);
        }
        // 将字符串加入对应的组
        map.get(sortedStr).push(str);
    }
    // 返回所有分组的数组
    return Array.from(map.values());
}

// 测试用例
const strs = ["eat", "tea", "tan", "ate", "nat", "bat"];
console.log(groupAnagrams(strs));

运行结果

对于输入 ["eat", "tea", "tan", "ate", "nat", "bat"],输出为:

[
  ["eat", "tea", "ate"],
  ["tan", "nat"],
  ["bat"]
]

扩展(优化排序法)

如果希望优化排序的时间,可以考虑使用字符计数代替排序,形成一个唯一的特征值,例如:

  • 对于 "eat",记录字符频率为 "1#1#1#0#0#...",用这种方式构建键。



✅ 128. 最长连续序列

题目 128:最长连续序列

给定一个未排序的整数数组,找出其中最长连续元素序列的长度。要求算法的时间复杂度为 O ( n ) O(n) O(n)


解题思路:

要实现 O ( n ) O(n) O(n) 的时间复杂度,我们可以利用哈希表(Set)来快速检查连续的数字是否存在:

  1. 将所有数字存入哈希表(Set
    • 使用哈希表存储数组中的所有数字,便于快速查找某个数字是否存在。
  2. 遍历数组,寻找序列的起点
    • 对每个数字 num,检查是否存在 num - 1
    • 如果不存在 num - 1,说明 num 是一个序列的起点。
    • num 开始,依次检查 num + 1 是否存在,计算序列的长度。
  3. 记录最长序列的长度
    • 在遍历过程中,更新最长序列长度。

Code:

复杂度分析

  1. 时间复杂度
    • 将数组转换为哈希表的时间复杂度是 O ( n ) O(n) O(n)
    • 遍历每个数字,并检查哈希表的操作为 O ( 1 ) O(1) O(1)
    • 每个序列中的数字最多只被遍历一次,因此整体时间复杂度为 O ( n ) O(n) O(n)
  2. 空间复杂度
    • 需要额外的哈希表存储所有数字,空间复杂度为 O ( n ) O(n) O(n)
/**
 * 最长连续序列
 * @param {number[]} nums
 * @return {number}
 */
function longestConsecutive(nums) {
    // 将数组转化为哈希集合
    const numSet = new Set(nums);
    let maxLength = 0;

    // 遍历数组中的每个数字
    for (const num of numSet) {
        // 如果 num 是序列的起点(num - 1 不存在)
        if (!numSet.has(num - 1)) {
            let currentNum = num;
            let currentLength = 1;

            // 找到当前序列的长度
            while (numSet.has(currentNum + 1)) {
                currentNum += 1;
                currentLength += 1;
            }

            // 更新最大长度
            maxLength = Math.max(maxLength, currentLength);
        }
    }

    return maxLength;
}

// 测试用例
const nums = [100, 4, 200, 1, 3, 2];
console.log(longestConsecutive(nums)); // 输出: 4 (最长序列是 [1, 2, 3, 4])





http://www.kler.cn/a/519349.html

相关文章:

  • 《CPython Internals》阅读笔记:p360-p377
  • 从曾国藩的经历看如何打破成长中的瓶颈
  • 中国认知作战研究中心:从认知战角度分析2007年iPhone发布
  • vim如何设置自动缩进
  • 【github 使用相关】提交pr和commit message Conventional Commits 规范 代码提交的描述该写什么?
  • 深度学习|表示学习|卷积神经网络|通道 channel 是什么?|05
  • 记录一个连不上docker中的mysql的问题
  • golang 使用双向链表作为container/heap的载体
  • python自动获取所需要的包并且保存到requirements.txt中
  • Redis高阶6-预热、雪崩、击穿、穿透问题
  • GoFrame MongoDB 使用指南
  • 【ESP32】ESP-IDF开发 | WiFi开发 | TCP传输控制协议 + TCP服务器和客户端例程
  • svn: E000111: Error running context: Connection refused
  • PCIe 个人理解专栏——【2】LTSSM(Link Training and Status State Machine)
  • 侧边栏布局和响应式布局的对比(Semi Design)
  • 查询本周一到周五的数据
  • STM32的Host U盘
  • vue3 el-form表格滚动
  • 数据库性能优化(sql优化)_SQL执行计划02_yxy
  • Kafka运维宝典 (三)- Kafka 最大连接数超出限制问题、连接超时问题、消费者消费时间超过限制问题详细介绍
  • Redis实战(黑马点评)——关于缓存(缓存更新策略、缓存穿透、缓存雪崩、缓存击穿、Redis工具)
  • AI x 长寿:OpenAI开发出逆龄AI GPT-4b micro
  • LabVIEW进行可靠性测试时有哪些常见的问题
  • 【MFC】C++所有控件随窗口大小全自动等比例缩放源码(控件内字体、列宽等未调整) 20250124
  • [LeetCode] 字符串 I — 344#反转字符串 | 541#反转字符串II | 54K替换数字
  • 如何获取小程序的code在uniapp开发中