hot100刷题记录-哈希

一、两数之和

题目:https://leetcode.cn/problems/two-sum/description/?envType=study-plan-v2&envId=top-100-liked
方法1:枚举

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for id, num in enumerate(nums):
            for idx, num_1 in enumerate(nums[id+1:]):
                if num + num_1 == target:
                    return [id, id + idx + 1]

两个指针,外部循环遍历全部列表,内部循环从原始列表的第二个数开始遍历,枚举所有可能的情况,判断是否等于目标数。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            for j in range(i + 1, len(nums)):
                if i != j and nums[i] + nums[j] == target:
                    return [i, j]
        return []

方法2:哈希表
新建一个字典,如果目标值减去当前值的差在字典里,那就说明存在这两个数之和等于目标值。如果没有,那就将当前值添加进字典。
遍历数组,对于每一个数 nums[i]nums[i]nums[i]:
先查找字典中是否存在 target−nums[i]target - nums[i]target−nums[i],存在则输出 target−nums[i]target - nums[i]target−nums[i] 对应的下标和当前数组的下标 iii。
不存在则在字典中存入 target−nums[i]target - nums[i]target−nums[i] 的下标 i。

def twoSum(self, nums: List[int], target: int) -> List[int]:
    numDict = dict()
    for i in range(len(nums)):
        if target-nums[i] in numDict:
            return numDict[target-nums[i]], i
        numDict[nums[i]] = i
    return [0]
  1. 首先,创建一个空字典 _dict 用来存储数组中每个元素的值和它们对应的索引。这样做的目的是为了快速查找数组中是否存在某个特定的值。
  2. 然后,使用一个循环遍历数组 nums 中的每一个元素。对于当前元素 nums[i],算法尝试找到一个数 x,使得 x + nums[i] = target。为了找到这样的数 x,我们可以将等式重写为 x = target - nums[i],然后查找 x 是否存在于之前遍历过的元素中。
  3. if target - nums[i] in _dict 这行代码就是检查 target - nums[i] 是否作为一个键(key)存在于字典 _dict 中。如果存在,这意味着我们找到了两个数 nums[i]x = target - nums[i],它们的和为 target
  4. 如果找到这样的一个数,return [_dict[target - nums[i]], i] 会返回这两个数的索引。其中 _dict[target - nums[i]] 是之前存储在字典中的与 x 相对应的索引,而 i 是当前 nums[i] 的索引。
    为什么要将减的值(即 x 对应的索引)放在前面,而将 i 放在后面呢?这是因为在遍历数组时,当前元素 nums[i] 的索引 i 总是大于或等于 x 对应的索引(因为 x 是在 nums[i] 之前出现的)。所以,当我们找到满足条件的一对数时,返回它们的索引时,x 对应的索引是较小的,而 i 是较大的,按照常规逻辑,我们习惯将较小的索引放在前面。
    这种方法的关键在于利用哈希表(即 Python 中的字典)来实现快速查找,这使得整个算法的时间复杂度降低到 O(n),其中 n 是数组 nums 的长度。

二、49. 字母异位词分组

题目链接地址
建立哈希表(字典),将相同的字母异位词有序化,作为键,变体作为值存储在列表里,最后取出字典的值放在列表里。

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        _dict = {}

        for i in strs:
            n_i = ''.join(sorted(i)) # # 对字符串排序,作为字典的键
            if n_i in _dict:
                _dict[n_i].append(i) # 如果键已存在,添加到对应的列表中
            else:
                _dict[n_i] = [i] # 如果键不存在,创建一个新的键并初始化列表

        return [i for i in _dict.values()] # 返回字典中所有值的列表
        # return list(_dict.values())  # 返回字典中所有值的列表

三、128. 最长连续序列

地址
思路:随机选择一个数,如果该数-1的值不存在于列表中,说明该数字不是有序数列中的中间和后面,是开头;
找到开头,再往后找,也就是加1,如果存在,那就给当前序列长度加一,然后继续往后找,直到不存在为止;
可能有很多连续序列,不可能每个序列长度都存储到一个序列中,所以要找到全局最长,每次和局部最长对比,取最长,这样最后就是全局最长的了。

def longestConsecutive(nums):
    # 创建一个集合,用于存储数组中的所有不重复的数字
    num_set = set(nums)
    longest = 0  # 初始化最长连续序列的长度为0

    # 遍历数组中的每个数字
    for num in nums:
        # 检查当前数字的前一个数字是否不在集合中
        # 如果不在,说明当前数字可能是一个连续序列的起点
        if num - 1 not in num_set:
            current_num = num  # 当前正在检查的数字
            current_streak = 1  # 当前连续序列的长度

            # 继续向后查找当前数字之后的连续数字
            while current_num + 1 in num_set:
                current_num += 1  # 移动到下一个数字
                current_streak += 1  # 增加连续序列的长度

            # 更新最长连续序列的长度
            longest = max(longest, current_streak)

    # 返回最长连续序列的长度
    return longest

四、283. 移动零

地址

快慢指针,快指针每次走一步,慢指针只在某种条件成立时才走一步。慢指针指向当前应该被替换的位置
条件:快指针遇到了非0值,将其往前替换,也就是跟慢指针的值交换,使得非0往左移动,0往右移动

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # 定义慢指针
        slow = 0
        # 快指针fast遍历列表
        for fast in range(len(nums)):
            # 当快指针位置不是0
            if nums[fast] != 0:
                # 替换,将当前快指针位置交换慢指针的值
                nums[fast], nums[slow] = nums[slow], nums[fast]
                # 交换过了,当前慢指针是非0值,所以往前走一步
                slow += 1

        return nums

循环过程:
遍历数组时,fast指针负责寻找非零元素。
当fast指针指向的元素不为0时,我们需要将其移到slow指针的位置。这是因为slow指针左侧的所有元素都已经处理过,即它们非零且保持了原有顺序。
交换nums[fast]和nums[slow]之后,我们增加slow指针的值,以指向下一个可能的替换位置。

五、11. 盛最多水的容器

地址
思路:对撞指针。一个从前往后,一个从后往前,计算两者间的面积。判断两个指针位置的高度,哪个低就把哪个指针移动。更新面积。退出条件:指针相遇。
**双指针必要条件:**要有终止条件(一般是两个指针相遇),未达到终止条件时要不断循环,在某个条件下移动这两个指针

本题本质上是 数组长度-1 * 最短高度 的最值问题,需要找到连续最优子数组和子最短高度
在这里插入图片描述

class Solution:
    def maxArea(self, height: List[int]) -> int:
        # 双指针 对撞指针
        pre = 0 # 前指针
        end = len(height) - 1 # 后指针
        marea = 0 # 最大面积

        # 当指针没遇到时,循环执行
        while pre < end:
            # 计算宽度,短板效应,选择两者间最短的
            y = (height[pre] if height[pre] < height[end] else height[end])
            # 计算长,指针位置的差
            x = end - pre # 长
            # 计算当前面积
            area = x * y
            
            # 更新最大面积
            if marea < area:
                marea = area
            
            # 如果左指针的值小于右边,就往右走一步
            if height[pre] < height[end]:
                pre += 1
            # 否则,右指针左移
            elif height[pre] >= height[end]:
                end -= 1
        # 从两个端点出发,考虑到所有可能的最优解,并记录过程中的最大值
        return marea

六、15. 三数之和

地址
最先想是直接三层遍历,但是一想就不可能是这样,太慢了。
依旧是对撞指针。
三数之和,如果把一个数固定,那就是两数之和。本题是双指针,可以用两个指针来指向另外两个数,成功实现降维。
先将数组进行排序,以保证按顺序查找时,元素值为升序,从而保证所找到的三个元素是不重复的。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        res = []

        # 排序
        # 如果有重复元素,就可以避过
        a = sorted(nums)


        for i in range(len(a)):
            # 将i的情况放在大于0的情况,防止溢出
            # 如果遇到重复元素,就跳过,因为题目不让重复
            if i >0 and a[i] == a[i-1]:
                continue
            
            # 定义左右指针
            l, r = i+1, len(a)-1
            # 当指针未相撞时,执行循环
            while l < r:
                # 如果当前遍历的位置和左右指针的值和为1,表明找到解了,添加到答案,然后移动左右指针
                if a[i] + a[l] + a[r] == 0:
                    res.append([a[i], a[l], a[r]])
                    l += 1
                    r -= 1
                # 如果说小于0,因为我们是排序了的,左边肯定比右边小,i又不能变,所以肯定是l太靠左了,加一右移
                elif a[i] + a[l] + a[r] < 0:
                    l += 1
                # 反之就是右边太大,左移
                else:
                    r -= 1
        # 虽然说上面是跳过了重复元素,但是也存在两个重复元素和其他的重复的都存在,导致有多个解是相同的
        # 将答案的每个元素排序后转为元组,因为列表不可哈希,用不了集合。集合去重
        unique_tuples = set(tuple(sorted(sublist)) for sublist in res)  # 去重并转换为集合
        nr = [list(tup) for tup in unique_tuples]  # 将元组转换回列表   

        return(nr)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

jmeter 按线程数阶梯式压测数据库

当前版本&#xff1a; jmeter 5.6.3mysql 5.7.39 简介 JMeter 通过 bzm - Concurrency Thread Group 来实现阶梯式压测&#xff0c;它并不是JMeter的官方插件&#xff0c;而是一种由Blazemeter提供的高级线程组插件。可以在不同的时间内并发执行不同数量的线程&#xff0c;模拟…

相册图片怎么压缩?3种方法教你压缩图片

相册图片怎么压缩&#xff1f;相册图片压缩在日常生活中扮演着至关重要的角色。它不仅能够帮助我们节省手机或电脑的存储空间&#xff0c;避免设备因存储空间不足而运行缓慢&#xff0c;还能显著减少图片在上传、下载或分享时的时间。此外&#xff0c;压缩图片还能在一定程度上…

[算法沉淀记录] 排序算法 —— 选择排序

排序算法 —— 选择排序 基本概念 选择排序是一种简单的排序算法&#xff0c;它的工作原理是每次从待排序的列表中选择最小&#xff08;或最大&#xff09;的元素&#xff0c;将其与列表中的第一个位置交换&#xff0c;然后继续对剩余的元素进行排序&#xff0c;直到整个列表…

【Java程序员面试专栏 算法思维】四 高频面试算法题:回溯算法

一轮的算法训练完成后,对相关的题目有了一个初步理解了,接下来进行专题训练,以下这些题目就是汇总的高频题目,本篇主要聊聊回溯算法,主要就是排列组合问题,所以放到一篇Blog中集中练习 题目关键字解题思路时间空间岛屿数量网格搜索分别向上下左右四个方向探索,遇到海洋…

R绘图 | 单列数据的分布图,对A变量分bin求B变量的平均值

问题1&#xff1a;单个向量的 density 分布图&#xff1f; (1) 模拟数据 set.seed(202402) datdiamonds[sample(nrow(diamonds), 1000),]> head(dat) # A tibble: 6 10carat cut color clarity depth table price x y z<dbl> <ord> &l…

数据可视化引领智慧仓储新时代

随着科技的飞速发展&#xff0c;数据可视化已然成为智慧仓储领域的璀璨明珠&#xff0c;其强大的功能和多面的作用让智慧仓储焕发出勃勃生机。让我们一同探索&#xff0c;数据可视化究竟在智慧仓储中起到了怎样的作用。下面我就以可视化从业者的角度来简单谈谈这个话题。 在这…

Linux——进程概念

目录 冯诺依曼体系结构 操作系统 管理 系统调用和库函数 进程的概念 进程控制块——PCB 查看进程 通过系统调用获取进程标示符 通过系统调用创建进程 进程状态 运行状态-R ​编辑 浅度睡眠状态-S 深度睡眠状态-D 暂停状态-T 死亡状态-X 僵尸状态-Z 僵尸进程…

详解顺序结构滑动窗口处理算法

&#x1f380;个人主页&#xff1a; https://zhangxiaoshu.blog.csdn.net &#x1f4e2;欢迎大家&#xff1a;关注&#x1f50d;点赞&#x1f44d;评论&#x1f4dd;收藏⭐️&#xff0c;如有错误敬请指正! &#x1f495;未来很长&#xff0c;值得我们全力奔赴更美好的生活&…

WPF 附加属性+控件模板,完成自定义控件。建议观看HandyControl源码

文章目录 相关连接前言需要实现的效果附加属性添加附加属性&#xff0c;以Test修改FontSize为例依赖属性使用触发器使用直接操控 结论 控件模板&#xff0c;在HandyControl的基础上面进行修改参考HandyControl的源码控件模板原型控件模板 控件模板触发器完整样式简单使用 结论 …

光学3D表面轮廓仪微纳米三维形貌一键测量

光学3D表面轮廓仪(白光干涉仪)利用白光干涉原理&#xff0c;以0.1nm分辨率精准捕捉物体的表面细节&#xff0c;实现三维显微成像测量&#xff0c;被广泛应用于材料学领域的研究和应用。 了解工作原理与技术 材料学领域中的光学3D表面轮廓仪&#xff0c;也被称为白光干涉仪&am…

低价对品牌渠道的危害

品牌价值的体现主要在价格&#xff0c;比如要与竞品体现差异&#xff0c;除了产品功能上有做出差异&#xff0c;价格上也需要设置不同的阶梯&#xff0c;但如果经销商不遵守这个体系&#xff0c;或者非授权店铺随意低价&#xff0c;对于品牌来说都是非常不好的事情&#xff0c;…

Django后台管理(二)

一、自定义注册管理类介绍 官网:Django 管理站点 | Django 文档 | Django 注册模型除了使用 Django 默认的管理类admin,也可以自定义,比如: class StudentAdmin(admin.ModelAdmin):pass admin.site.register(Student, StudentAdmin)ModelAdmin 类是管理界面中模型的表示。…

微信小程序 wxs内联与外联的写法

内联写法 <!-- 内联wxs --> <view>大写字母{{m1.toUpper("xmly")}}</view> <wxs module"m1">module.exports.toUpperfunction(str){return str.toUpperCase()} </wxs> 外联写法 新建一个wxs文件 写一个函数&#xff0c;将…

架构(十五)Java字节码增强

一、引言 一般如果需要做增强类的架构工具会使用SpringBoot提供的切面&#xff0c;但是这逃不开两个问题&#xff1a;1、使用方需要加注解代码&#xff1b;2、版本更新导致的发布。 所以java还提供了字节码层面的增强方案&#xff0c;对使用的系统是无感的。 二、字节码增强选…

BLEU: a Method for Automatic Evaluation of Machine Translation

文章目录 BLEU: a Method for Automatic Evaluation of Machine Translation背景和意义技术原理考虑 n n n - gram中 n 1 n1 n1 的情况考虑 n n n - gram中 n > 1 n\gt 1 n>1 的情况考虑在文本中的评估初步实验评估和结论统一不同 n n n 值下的评估数值考虑句子长度…

Ubuntu上Jenkins自动化部署Gitee上SpringBoot项目

文章目录 安装安装JDK安装Maven安装GitNodeJS安装&#xff08;可选&#xff09;安装Jenkins 配置Jenkins为Jenkins更换插件源设置jenkins时区安装插件全局工具配置添加Gitee凭证Gitee项目配置 部署后端1.新建任务2.配置源码管理3.构建触发器4.到Gitee中添加WebHook5.构建环境6.…

C++——基础语法(3):内联函数、auto关键字、基于范围的for循环、空指针nullptr

6. 内联函数 在函数前加入inline修饰即可将函数变为内联函数。所谓内联函数&#xff0c;就是在编译时C编译器会将函数体在调用内联函数的地方展开&#xff0c;从而省去了调用函数的栈帧开销&#xff0c;提高程序运行效率。 inline int Add(int a, int b) {return a b; } int …

十一、计算机视觉-膨胀操作

文章目录 前言一、什么是膨胀二、膨胀操作的实现1.引入库 三、膨胀的原理 前言 上节我们学习了腐蚀操作&#xff0c;本节我们讲一下膨胀操作&#xff0c;膨胀和腐蚀实际上是相反的操作。上节我们把云峰这2个字周围没用的像素去掉了&#xff0c;但是云峰这2个字也变细了&#x…

Protocol Buffer-nanopb介绍

文章目录 一、需求二、环境三、相关概念3.1 protocol buffer介绍3.2 nanopb&#xff08;支持C语言&#xff09;3.3 proto文件 四、proto基本语法4.1 proto文件的定义4.2 字段规则4.3 字段类型4.4 字段编号4.5 proto语法4.6 进阶语法4.6.1 message嵌套4.6.2 enum关键字4.6.3 one…