Leetcod面试经典150题刷题记录 —— 哈希表篇

news2025/4/19 18:01:39

Leetcod面试经典150题刷题记录 —— 哈希表篇

    • 1. 赎金信
    • 2. 同构字符串(按逻辑完整性,分次书写代码)
    • 3. 单词规律
    • 4. 有效的字母异位词
      • 4.1 进阶: 输入字符串包含 unicode 字符
    • 5. 字母异位词分组
    • 6. 两数之和
    • 7. 快乐数
      • hash集合检测循环
      • 隐式链表+快慢指针(弗洛伊德循环查找算法)
      • 数学+仿真(待完成)
    • 8. 存在重复元素 II
      • 8.1 我的原始解法(遍历数组+遍历hash表)
      • 8.2 记录最大下标解法
      • 8.3 滑动窗口法
    • 9. 最长连续序列(有个语法问题,待解决)

1. 赎金信

题目链接:赎金信 - leetcode
题目描述:
给你两个字符串:ransomNotemagazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。如果可以,返回 true ;否则返回 falsemagazine 中的每个字符只能在 ransomNote 中使用一次。
题目归纳:
统计字符频率并比较即可

解题思路:
(1) 解法: 赎金信 - leetcode官方题解

from collections import Counter

class Solution:
    def canConstruct(self, ransomNote: str, magazine: str) -> bool:
        # magzine的字符词频绝对 >= ransomNote即可啊
        r_counter = Counter(ransomNote)
        m_counter = Counter(magazine)
        return m_counter >= r_counter

2. 同构字符串(按逻辑完整性,分次书写代码)

题目链接:同构字符串 - leetcode
题目描述:
给定两个字符串 st ,判断它们是否是同构的。如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的。每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序。不同字符不能映射到同一个字符上,相同字符只能映射到同一个字符上,字符可以映射到自己本身。
题目归纳:
s[i]t[i]是否互相是一一映射

解题思路:
(1) 解法: 同构字符串 - leetcode官方题解

这里值得说一点的是,写代码不一定是遵守代码完整性,从上到下完整书写,应遵循逻辑完整的原则,这一点也是我写了这么久代码的一点小心得,人做一切事情都是会遵循逻辑和规律,不能是碎片化的,例如这里,应该按这样的顺序写:

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        # 两个字典
        s2t = dict()
        t2s = dict()
        s_len = len(s)

        for i in range(s_len):
            # 先构建映射
            ch_s = s[i]
            ch_t = t[i]          
            s2t[ch_s] = ch_t
            t2s[ch_t] = ch_s

        return True

再添加判断逻辑,将上面的代码块变成下面的

class Solution:
    def isIsomorphic(self, s: str, t: str) -> bool:
        # 两个字典
        s2t = dict()
        t2s = dict()
        s_len = len(s)

        for i in range(s_len):
            ch_s = s[i]
            ch_t = t[i]       
            # 再添加映射失败的判断逻辑
            if (ch_s in s2t and s2t[ch_s] != ch_t) or (ch_t in t2s and t2s[ch_t] != ch_s):
                return False     
            s2t[ch_s] = ch_t
            t2s[ch_t] = ch_s

        return True

3. 单词规律

题目链接:单词规律 - leetcode
题目描述:
给定一种规律 pattern 和一个字符串 s ,判断 s 是否遵循相同的规律。这里的 遵循 指完全匹配,例如, pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。
题目归纳:
先把s' '进行split(),得到分词数组S,就回归到了上一题:同构字符串

解题思路:
(1) 解法: 单词规律- leetcode官方题解

class Solution:
    def wordPattern(self, pattern: str, s: str) -> bool:
        # 先把s按空格进行split就回归到上一题:同构字符串
        S = s.split()
        S_len = len(S)
        p_len = len(pattern)
        if S_len != p_len:
            return False

        p2S = dict()
        S2p = dict()

        for i in range(p_len):
            ch_p = pattern[i]
            word_S = S[i]
            if (ch_p in p2S and p2S[ch_p] != word_S) or (word_S in S2p and S2p[word_S] != ch_p):
                return False
            
            p2S[ch_p] = word_S
            S2p[word_S] = ch_p
        
        return True

4. 有效的字母异位词

题目链接:有效的字母异位词 - leetcode
题目描述:
给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。
题目归纳:
字符频率相同即可

解题思路:
(1) 解法: 有效的字母异位词 - leetcode官方题解

from collections import Counter

class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return Counter(s) == Counter(t) # 字符频率相同即可

4.1 进阶: 输入字符串包含 unicode 字符

5. 字母异位词分组

题目链接:字母异位词分组 - leetcode
题目描述:
给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:
输入: strs = [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”]
输出: [[“bat”],[“nat”,“tan”],[“ate”,“eat”,“tea”]]

题目归纳:
相同字符频率的字符串放一起作为value,那么key就是其对应的字典序母串

解题思路:
(1) 解法: 字母异位词分组 - leetcode官方题解

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        # 字符频率一致的放一起
        sortedS_dysWords = dict() # 变量命名法:key_value dystopia n. 异位;非理想化的地方,糟透的社会;地狱般的处境
        n = len(strs)
        
        for S in strs:
            key = "".join(sorted(S))
            if key in sortedS_dysWords: # 该str经排序后,存在于hash表中,说明其字符频率出现过
                sortedS_dysWords[key].append(S)
            else:
                sortedS_dysWords[key] = [S]
        
        ans = []
        for key in sortedS_dysWords:
            value = sortedS_dysWords[key]
            ans.append(value)
        return ans

6. 两数之和

题目链接:两数之和 - leetcode
题目描述:
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。

示例 1:
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

题目归纳:
解题思路:数组的索引方式是由下标index --> 元素值value,可以用一个hash表反向存储,由元素值value --> 下标index

解题思路:
(1) 解法: 两数之和 - leetcode官方题解

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hash_table = dict() # key:val = index:nums[index],相当于反向存储数组
        for i, num in enumerate(nums): # 一次遍历即可
            if target - num in hash_table:
                return [i, hash_table[target-num]]
            else: # 数组是key:value = 下标:元素值,这里是key:value=元素值:下标
                hash_table[num] = i 
        return []

7. 快乐数

题目链接:快乐数 - leetcode
题目描述:
编写一个算法来判断一个数 n 是不是快乐数。「快乐数」 定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1,那么这个数就是快乐数。如果 n 是 快乐数 就返回 true ;不是,则返回 false

示例 1:
输入:n = 19
输出:true
解释:
12 + 92 = 82
82 + 22 = 68
62 + 82 = 100
12 + 02 + 02 = 1
提示
1 <= n <= 231 - 1,即 1 <= n <= 2147483647,换算成十进制,n最高也只有10位数字。

题目归纳:
看上去可以用仿真法,但是由于图灵停机问题:“给定一段算法和输入组成程序A,你找不到一段通用程序B,去判断程序A是否会陷入无限循环”,所以这道题你没有一个通用的判定方法,来判断是否会无限循环,除非你能找到那些会陷入无限循环的数字,官方题解在之后就给出了这样的一个无限循环,在 1 <= n <= 231 - 1 的情况下,这样的循环有且只有一个。

解题思路:
解法: 快乐数 - leetcode官方题解
(1) 用hash集合检测循环。
(2) 隐式链表+快慢指针(又称为弗洛伊德循环查找算法)检测循环。
(3) 数学法确定循环数字 + 仿真。
这道题的关键点在于死循环数字的检测上

开端循环赵今麦

hash集合检测循环

def get_next(n):
    total = 0
    while n > 0:
        digit = n%10
        total += digit**2
        n = int(n/10)
    return total

class Solution:
    def isHappy(self, n: int) -> bool:
        seen = set()
        while n != 1 and n not in seen: # 不在seen集合中,就是不在循环中
            seen.add(n)
            n = get_next(n)
        return n == 1

隐式链表+快慢指针(弗洛伊德循环查找算法)

def get_next(n):
    total = 0
    while n > 0:
        digit = n%10
        total += digit**2
        n = int(n/10)
    return total

class Solution:
    def isHappy(self, n: int) -> bool:
        slow_p = n
        fast_p = get_next(n)
        while fast_p != 1 and slow_p != fast_p : # fast指针没到终点,并且slow没追上fast,游戏就没结束
            slow_p = get_next(slow_p) # 1 step 
            fast_p = get_next(get_next(fast_p)) # 2 step
        return fast_p == 1 # 走到了终点吗?

数学+仿真(待完成)

class Solution:
    # 在没有确定循环数字前,模拟的思路是错误的
    def squareSum(self, num: int) -> int:
        ans = 0
        while num != 0:
            x = num % 10
            ans += x**2
            num = int(num/10)
        return ans

    def isHappy(self, n: int) -> bool:
        while n != 1:
            n = self.squareSum(n)
        return True

8. 存在重复元素 II

题目链接:存在重复元素 II - leetcode
题目描述:
给你一个整数数组 nums 和一个整数 k ,判断数组中是否存在两个 不同的索引 ij ,满足 nums[i] == nums[j]abs(i - j) <= k 。如果存在,返回 true ;否则,返回 false
题目归纳:
(1)我一开始的解法是遍历数组+遍历hash表
(2)最大下标解法。
(3)滑动窗口法。

解题思路:
解法: 存在重复元素 II - leetcode官方题解

8.1 我的原始解法(遍历数组+遍历hash表)

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        # 相同value,其下标index_i添加到hash表中
        # 建立hash表 key:val = value:[index_1, ...]
        # 遍历hash表的下标数组,查找是否存在 abs(i-j) <= k
        hash_table = dict()
        
        # (1)遍历数组,并添加元素至hash表中
        for i,num in enumerate(nums):
            if num in hash_table:
                hash_table[num].append(i)
            else: # 建立数组
                hash_table[num] = [i]

        print(hash_table)
        # (2)遍历hash表,查找是否有index满足 abs(i-j) <= k
        for value in hash_table:
            indices = hash_table[value]
            for i in indices:
                for j in indices:
                    if i != j and abs(i-j)<=k: # 必须是不同的索引
                        return True

        return False

8.2 记录最大下标解法

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        pos = dict()
        for i,num in enumerate(nums):
            if num in pos and i - pos[num] <= k: # i 一直比当前的pos[num]大
                return True
            pos[num] = i # 记录最大的下标
        return False

8.3 滑动窗口法

class Solution:
    def containsNearbyDuplicate(self, nums: List[int], k: int) -> bool:
        # 滑动窗口法
        # (1)nums中,每个长度不超过k+1的滑动窗口,其任意两个下标i,j,一定满足abs(i-j)<=k
        # (2)若存在一个滑动窗口,其中有重复元素,则一定存在两个不同的下标i,j,满足nums[i] = nums[j] and abs(i-j) <= k
        # (3)若该滑动窗口没有重复元素,则不符合要求,继续遍历滑动窗口
        # (4)若一个滑动窗口的结束下标是i,则开始下标是max(0,i-k)
        # (5)使用哈希集合,存储滑动窗口中的元素,从左至右遍历数组nums
        # (6)若 i > k,则i-(k+1)处的元素被移出滑动窗口,即s.remove(nums[i-k-1])
        # (7)若nums[i]在哈希集合中,则在同一个滑动窗口中有重复元素,不在哈希集合中则将其加入集合。

        window = set()
        for i, num in enumerate(nums):
            if i > k: # (1)维持窗口大小
                window.remove(nums[i-(k+1)])
            if num in window: # (2)判断窗口是否出现相同元素
                return True
            window.add(num)
        return False

9. 最长连续序列(有个语法问题,待解决)

题目链接:最长连续序列 - leetcode
题目描述:
给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。请你设计并实现时间复杂度为 O(n) 的算法解决此问题。
题目归纳:

解题思路:
解法: 最长连续序列 - leetcode官方题解

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        longest_streak = 0
        num_set = set(nums) #去重,时间复杂度O(n),想到用set()是非常关键的

        for num in num_set:
            if num - 1 not in num_set: # 若存在前驱数,则跳过。判断的时间复杂度是O(1)
                current_num = num
                current_streak = 1

                # next_num = num + 1 # ???不能用next_num? 离大谱了!!
                # while next_num in num_set: # 这行搭配上面这行会超时,实在离谱
                while current_num+1 in num_set: # 判断的时间复杂度是O(1)
                    current_num += 1
                    current_streak += 1

                longest_streak = max(longest_streak, current_streak)

        return longest_streak

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1331526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

非线性约束的优化问题_序列二次规划算法代码

1. 理论部分 2. 序列二次规划算法代码及解析 3.完整代码 1.理论部分 a.约束优化问题的极值条件 库恩塔克条件(Kuhn-Tucker conditions&#xff0c;KT条件)是确定某点为极值点的必要条件。如果所讨论的规划是凸规划&#xff0c;那么库恩-塔克条件也是充分条件。 &#xff…

JBoss JMXInvokerServlet 反序列化漏洞 CVE-2015-7501 已亲自复现

JBoss JMXInvokerServlet 反序列化漏洞 CVE-2015-7501 已亲自复现 漏洞名称漏洞描述影响版本 漏洞复现环境搭建漏洞利用 修复建议总结 漏洞名称 漏洞描述 在Oracle Rapid Planning 12.1/12.2.2中发现了一个被归类为“严重”的漏洞。受到影响的是一些未知的组件处理中间层。升…

SQL进阶理论篇(二十):什么是SQL注入

文章目录 简介SQL注入的原理SQL注入的实例搭建sqli-labs注入环境实例一&#xff1a;猜测where条件判断查询语句的字段数获取当前数据库和用户信息获取MySQL中的所有数据库名称查询wucai数据库中的所有数据表查询heros数据表中的所有字段参考文献 简介 这节是纯兴趣篇了。 web…

RocketMQ事务消息实现分布式事务

文章目录 简介实现原理实现逻辑 简介 RocketMQ事务消息 RocketMQ在4.3.0版中支持分布式事务消息&#xff0c;这里RocketMQ的事务消息是采用2PC(两段式协议) 补偿机制&#xff08;消息回查&#xff09;的分布式事务功能。提供消息发送与业务落库的一致性。 RocketMQ事务消息&am…

MicroPython的交互式解释器模式 REPL

MicroPython的交互式解释器模式又名REPL&#xff08;read-eval-print-loop&#xff09;&#xff0c;就是一种命令输入交互模式&#xff0c;跟Python的REPL是类似的&#xff0c;就是在命令行直接输入Python代码或表达式执行并打印结果。关于MicroPython的REPL跟通常的Python类似…

电子病历编辑器源码,提供电子病历在线制作、管理和使用的一体化电子病历解决方案

概述&#xff1a; 电子病历是指医务人员在医疗活动过程中,使用医疗机构信息系统生成的文字、符号、图表、图形、数据、影像等数字化信息,并能实现存储、管理、传输和重现的医疗记录,是病历的一种记录形式。 医院通过电子病历以电子化方式记录患者就诊的信息&#xff0c;包括&…

【常见的语法糖(详解)】

&#x1f7e9; 说几个常见的语法糖 &#x1f7e2;关于语法糖的典型解析&#x1f7e2;如何解语法糖&#xff1f;&#x1f7e2;糖块一、switch 支持 String 与枚举&#x1f4d9;糖块二、泛型&#x1f4dd;糖块三、自动装箱与拆箱&#x1f341;糖块四、方法变长参数&#x1f5a5;️…

Linux多线程:POSIX信号量,基于信号量的环形队列实现生产者消费者模型

目录 一、POSIX信号量1.1 初始化信号量1.2 销毁信号量1.3 等待信号量1.4 发布信号量1.5 基于环形队列的生产消费模型(用信号量控制生产者和消费者之间的同步互斥关系)1.5.1 makefile1.5.2 RingQueue.hpp1.5.3 Sem.hpp1.5.4 Task.hpp1.5.5 main.cc 二、信号量控制的环形队列原理…

.Net 访问电子邮箱-LumiSoft.Net,好用

序言&#xff1a; 网上找了很多关于.Net如何访问电子邮箱的方法&#xff0c;但是大多数都达不到想要的需求&#xff0c;只有一些 收发邮件。因此 花了很大功夫去看 LumiSoft.Net.dll 的源码&#xff0c;总算做出自己想要的结果了&#xff0c;果然学习诗人进步。 介绍&#xff…

Qt 开源项目

Qt 开源项目 Omniverse View链接技术介绍 QuickQanava链接技术介绍QField链接技术介绍 AtomicDEX链接技术介绍 Status-desktop链接技术介绍 Librum链接技术介绍 A Simple Cross-Platform ReaderQPrompt链接技术介绍 GCompris链接技术介绍 Scrite链接技术介绍 QSkinny链接技术介…

如何在PC上运行大模型

如何在PC上运行大模型 在PC上使用CPU运行大模型不如使用GPU高效&#xff0c;但仍然是可以实现的大模型推理。 大模型训练要求的资源更高&#xff0c;这里直接使用面向开源的Facebook’s LLaMA model(llama-2-7b-chat.Q2_K.gguf)。 连接CPU与LLaMA model的是llama.cpp。 为方便…

认识Linux背景

1.发展史 Linux从哪里来&#xff1f;它是怎么发展的&#xff1f;在这里简要介绍Linux的发展史 要说Linux&#xff0c;还得从UNIX说起 UNIX发展的历史 1968年&#xff0c;一些来自通用电器公司、贝尔实验室和麻省理工学院的研究人员开发了一个名叫Multics的特殊操作系统。Mu…

LLaMA开源大模型源码分析!

Datawhale干货 作者&#xff1a;宋志学&#xff0c;Datawhale成员 花了一晚上照着transformers仓库的LLaMA源码&#xff0c;把张量并行和梯度保存的代码删掉&#xff0c;只留下模型基础结构&#xff0c;梳理了一遍LLaMA的模型结构。 今年四月份的时候&#xff0c;我第一次接触…

第一次记录QPSK,BSPK,MPSK,QAM—MATLAB实现

最近有偶然的机会学习了一次QPSK防止以后忘记又得找资料&#xff0c;这里就详细的记录一下 基于 QPSK 的通信系统如图 1 所示&#xff0c;QPSK 调制是目前最常用的一种卫星数字和数 字集群信号调制方式&#xff0c;它具有较高的频谱利用率、较强的抗干扰性、在电路上实现也较为…

基于STM32单片机模拟智能电梯步进电机控制升降毕业设计3

STM32单片机模拟智能电梯步进电机控制数码管显示3 演示视频&#xff08;复制到浏览器打开&#xff09;&#xff1a; 基于STM32单片机的智能电梯控制系统模拟智能电梯步进电机控制系统设计数码管显示楼层设计/DIY开发板套件3 产品功能描述&#xff1a; 本系统由STM32F103C8T6单…

技术交底二维码的应用

二维码技术交底可以逐级落实、责任到人、有据可查、是目前最方便、实用的交底方式&#xff0c;下面我们讲解技术交底二维码的应用。 1、生成对应的技术交底二维码&#xff0c;将施工方案、技术资料、安全教育资料等内容上传到二维码里。打印出来现场粘贴&#xff0c;便于作业班…

(一)深入理解Mysql底层数据结构和算法

什么是索引 索引是帮助MySQL高效获取数据的排好序的数据结构 数据结构有哪些 数据结构模拟网站&#xff1a;Data Structure Visualization 二叉树 不适合做自增ID的数据结构。如下示意图&#xff0c;假设采用二叉树作为表自增主键ID的数据存储结果如下&#xff1a;当查询i…

行列式:方程组未知数的计算:克拉默法则

行列式&#xff1a;方程组未知数的计算 ![ ](https://img-blog.csdnimg.cn/direct/4a9c2800da3746ea95c1a3c93057d796.png)

VS Code实现“Ctr+save”保存代码自动格式化

一、下载Prettier - Code formatter插件 点击安装即可 二、配置 【1】打开文件——首选项——设置 或者左下角齿轮打开设置 【2】搜索设置框输入editor default formatter&#xff08;意思是默认格式化设置&#xff09;&#xff0c;接着下拉选中刚下好的插件名称Prettier - C…

【Vulnhub 靶场】【Corrosion: 1】【简单】【20210731】

1、环境介绍 靶场介绍&#xff1a;https://www.vulnhub.com/entry/corrosion-1,730/ 靶场下载&#xff1a;https://download.vulnhub.com/corrosion/Corrosion.ova 靶场难度&#xff1a;简单 发布日期&#xff1a;2021年07月31日 文件大小&#xff1a;7.8 GB 靶场作者&#xf…