知识储备--基础算法篇-Hash table

news2024/11/25 0:53:44

1.哈希表的基础概念

哈希表是一种数据结构,它使用哈希函数将键映射到存储桶或槽位中。它通过将键转换为索引来实现快速的插入、查找和删除操作。哈希表通常用于需要高效查找的场景,如字典、缓存和数据库中。

常见哈希结构

  1. 数组
  2. set(集合)
  3. map(映射)-py里面是dict (字典)
    py中的set为无序的不可重复的key。
    字典包含key和value

当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法!

看这篇博文应该就能对哈希表有个基础的了解了。来吧!一文彻底搞定哈希表!_哈希表庆哥_庆哥Java的博客-CSDN博客

2.算法实战 

2.1第1题

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target  的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

(1)暴力枚举法

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        left = 0
        right = 0
        for i in range(len(nums)):
            for j in range(left+1,len(nums)):
                if nums[j] + nums[left] == target:
                    return [left,j]
                else:
                        j = j + 1
            left = left + 1

时间很长,没想到这也能打败10%。

(2)哈希表

class Solution(object):
    def twoSum(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        hash_table = dict()
        for i, num in enumerate(nums):
            if target - num in hash_table:
                return [hash_table[target-num], i]
            else:
                hash_table[num] = i

2.2第49题

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

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

心得:该题主要是找到具有相同字母的异构单词之间的共性,提取出来作为哈希表的键,值就是具有相同字母的异构单词列表。没做出来,想到了用数字代替字母排序,但是只想到了加法,觉得不具有唯一性就没用。看了讨论区,大佬用质数的方法代替字母,这样质数的乘积是唯一的,相同字母组成的异构单词就具有相同的性质,就可以用字典来储存表示了。官方答案写的没看懂。

class Solution(object):
    def groupAnagrams(self, strs):
        """
        :type strs: List[str]
        :rtype: List[List[str]]
        """
        map = {
            'a':2,'b':3,'c':5,'d':7,'e':11,'f':13,'g':17,'h':19,'i':23,'j':29,'k':31,'l':37,'m':41,
            'n':43,'o':47,'p':53,'q':59,'r':61,'s':67,'t':71,'u':73,'v':79,'w':83,'x':89,'y':97,'z':101
        }
        resmap={}
        reslist = []
        for str in strs:
            m = 1
            for i in range(len(str)):
                m*=map[str[i]]
            if  not m in resmap:
                resmap[m]=[]
            resmap[m].append(str)
        # print(resmap.values())
        return [j for j in resmap.values()]

2.3第128题

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

心得:哈希表实在掌握的太差,只能用最蠢的方法暴力解出来,但是时间已经超出限制了。

class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums)==0:
            return 0
        if len(nums)==1:
            return 1
        i = 0
        j = 0
        cur_len = 1
        max_len = 1
        for i in range(len(nums) - 1):
            for j in range(len(nums) - 1 - i):
                if nums[j] > nums[j+1]:
                    temp = nums[j+1]   
                    nums[j+1] = nums[j]
                    nums[j] = temp
        
        for k in range(len(nums) - 1):
            if nums[k+1]==nums[k]:
                continue
            elif nums[k+1]==nums[k] + 1:
                cur_len = cur_len + 1
                if max_len < cur_len:
                    max_len = cur_len
            else:
                cur_len = 1
        return max_len


        
        
        return nums
        

看了一眼解析,发现使用的set(),只能说掌握的知识太少了,去看了set()的用法后自己终于写出来了一版。但是时间和内存的消耗还是很大。

class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        up = 1
        down = 1
        cur_len = 1
        max_len = 1
        if len(nums)==0:
            return 0
        if len(nums)==1:
            return 1
        hash_table = set()
        for i in range(len(nums)):
            hash_table.add(nums[i])
        j = 0
        while j < len(nums)-1:
            hash_table.discard(nums[j])
            if nums[j] + up in hash_table:
                hash_table.remove(nums[j] + up)
                up = up + 1
            elif nums[j] - down in hash_table:
                hash_table.remove(nums[j] - down)
                down = down + 1
            else:
                cur_len = up + down - 1
                up = 1
                down = 1
                if cur_len > max_len:
                    max_len = cur_len
                j = j + 1
        return max_len
        

 发现可以hash_table=set(nums),内存减少了一些,竟然击败增加了这么多。

 看了官方的答案写出来的一版。更加的简洁。

class Solution(object):
    def longestConsecutive(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        cur_len = 1
        max_len = 1
        if len(nums)==0:
            return 0
        if len(nums)==1:
            return 1
        hash_table = set(nums)
        for num in hash_table:
            if num - 1 not in hash_table:
                # 如果表中没有比它小1的,就开始寻找大1的,然后一直往上找
                cur_num = num
                cur_len = 1
                # 如果比它大1存在,则开始计数
                while cur_num + 1 in hash_table:
                    cur_num = cur_num + 1
                    cur_len = cur_len + 1
                if max_len < cur_len:
                    max_len = cur_len
            # 如果有比它小1的,直接不管,继续循环,直到找到没有比它小1的

        return max_len
        

3.总结

做完哈希表的题发现有几个重点,一个是什么时候用,在需要快速查找一个元素是否在集合里时,就要用到哈希表。一个是需要掌握数组,dict(),set()的基础用法,不然真的很麻烦。

4.需要掌握的知识

4.1数组基本用法

1、Python的数组分三种类型:
(1) list 普通的链表,初始化后可以通过特定方法动态增加元素。
定义方式:arr = [元素]

文章python数组使用(超级全面)_27Up的博客-CSDN博客

  1. a、定义时初始化,a = [1,2,[1,2,3]],b、定义时不初始化,一维数组:arr = []
  2. del 删除数组里的指定元素,如: del arr[0]
  3. d、遍历数组:
    for k, v in enumerate(arr):
    print k, v
  4. e、增加元素:一维arr.append('aaa'),二维arr[0].append('aaa')
    如果要在任意位置插入用 arr.insert(n, 值)
  5. list的方法
    L.append(var) #追加元素
    L.insert(index,var)
    L.pop(var) #返回最后一个元素,并从list中删除之
    L.remove(var) #删除第一次出现的该元素
    L.count(var) #该元素在列表中出现的个数
    L.index(var) #该元素的位置,无则抛异常
    L.extend(list) #追加list,即合并list到L上
    L.sort() #排序
    L.reverse() #倒序

(2) Tuple 固定的数组,一旦定义后,其元素个数是不能再改变的。
定义方式:arr = (元素)

Tuple 没有的方法:
[1] 不能向 tuple 增加元素,没有 append 、 extend 、insert 等方法。
[2] 不能从 tuple 删除元素,没有 remove 或 pop 方法。
[3] 不能在 tuple 中查找元素,没有 index 方法(index是查找而不是索引,索引直接用下标即可,如:t[0])。

Tuple 可以转换成 list, 反之亦然。
转换方式为:t = list( t ),反之:arr = tuple( arr )

(3) Dictionary 词典类型, 即是Hash数组。
定义方式:arr = {元素k:v}

#Dictionary 的用法比较简单,它可以存储任意值,并允许是不同类型的值,下面实例来说明:
#下面例子中 a 是整数, b 是字符串, c 是数组,这个例子充分说明哈希数组的适用性。
dict_arr = {'a': 100, 'b':'boy', 'c':['o', 'p', 'q']}

#可以直接增加一个元素,如果同名,则会改变原来的key的元素的值
dict_arr['d'] = 'dog'

#输出所有的key
print dict_arr.keys()

#输出所有的value
print dict_arr.values()

4.2dict()基本用法

  1. 当我们不需要这个元素时,需要把元素从dict中删除,pop()方法快速删除元素。但需要指定需要删除元素的key,并返回value。<**注>**pop()方法的参数是dict中的key,当key不存在时,同样会引起错误。
  2. 读取dict 元素。创建一个dict ,dict 通过key找到对应的value的功能。还可以通过key来获取对应的value,dict提供get方法,把key当作参数传递给get方法。当Key不存在时也不会出错。
  3. 添加dict元素dict和tuple不一样,dict是可变的,我们随时可以往dict中添加新的key-value,value可以是任意类型的元素,可以是list、tuple等,如d['Alice'] =[50,61,66]赋值语句有两个功能:
    1.当key不存在时,往dict中添加对应的key:value元素。
    2.当key存在时,会更新dict,用新的value 替换原来的value。
  4. python遍历dict遍历dict有两种方法
    第一种是遍历dict的所有key,并通过key获得对应的value。
    第二种方法是通过dict提供的items()方法,items()方法会返回dict中所有的元素,每个元素包含key和value。for key,value in d.items():
  5. 清除所有元素dict 提供clear()函数,直接清除dict 中所有元素。d.clear()

4.1set()基本用法

文章Python 集合set详解(超详细)_python set集合_LeoATLiang的博客-CSDN博客

  1. 集合(set)是一个无序不重复元素序列。
  2. 可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典。
  3. 我们无法通过引用索引来访问 set 中的项目,因为 set 是无序的,项目没有索引。但是可以使用 for 循环遍历 set 项目,或者使用 in 关键字查询集合中是否存在指定值。
  4. add() 方法用于给集合添加元素,如果添加的元素在集合中已存在,则不执行任何操作。
  5. update() 方法用于修改当前集合,可以添加新的元素或集合到当前集合中,如果添加的元素在集合中已存在,则该元素只会出现一次,重复的会忽略。update()可以合并两个集合。
  6. remove() 方法用于移除集合中的指定元素。该方法不同于 discard() 方法,因为 remove() 方法在移除一个不存在的元素时会发生错误,而 discard() 方法不会。

  7. clear() 方法用于移除集合中的所有元素。

  8. 删除则使用del函数

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

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

相关文章

系统架构设计专业技能 · 数据库设计

系列文章目录 系统架构设计专业技能 软件工程&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 软件架构概念、架构风格、ABSD、架构复用、DSSA&#xff08;一&#xff09;【系统架构设计师】 系统架构设计高级技能 系统质量属性与架构评估&#xff08;…

高频面试题:多线程顺序打印ABC字符20次

一个关于多线程协作的题目经常会出现在大厂的面试中&#xff1a;有三个线程分别打印A、B、C&#xff0c;请让这三个线程按顺序打印出ABC20次。 我们知道&#xff0c;线程调度机制是非确定性的&#xff0c;如果不加上额外的并发控制&#xff0c;直接启动三个线程&#xff0c;那么…

【软件测试】Java和Python做自动化测试哪个更有优势?

Java和Python做自动化测试&#xff0c;哪个更有优势&#xff1f;这两个语言都是很流行的语言&#xff0c;所以从技术上很难说谁好谁不好的。因为要说好不好得看使用的环境和要求。就像生活在中国&#xff0c;你天天说英语&#xff0c;别人会说你“又拽鸟语啊”&#xff1f;但是…

Postman的高级用法—Runner的使用​

1.首先在postman新建要批量运行的接口文件夹&#xff0c;新建一个接口&#xff0c;并设置好全局变量。 2.然后在Test里面设置好要断言的方法 如&#xff1a; tests["Status code is 200"] responseCode.code 200; tests["Response time is less than 10000…

接口自动化中如何完成接口加密与解密?

加密是一种限制对网络上传输数据的访问权的技术。将密文还原为原始明文的过程称为解密&#xff0c;它是加密的反向处理。在接口开发中使用加密、解密技术&#xff0c;可以防止机密数据被泄露或篡改。在接口自动化测试过程中&#xff0c;如果要验证加密接口响应值正确性的话&…

简单认识镜像底层原理详解和基于Docker file创建镜像

文章目录 一、镜像底层原理1.联合文件系统(UnionFS)2.镜像加载原理3.为什么Docker里的centos的大小才200M? 二、Dockerfile1.简介2.Dockerfile操作常用命令 三、创建Docker镜像1.基于已有镜像创建2.基于本地模板创建3.基于Dockerfile创建4.Dockerfile多阶段构建镜像 一、镜像底…

卷积神经网络全解:(AlexNet/VGG/ GoogLeNet/LeNet/ResNet/卷积/激活/池化/全连接)、现代卷积神经网络、经典卷积神经网络

CNN&#xff0c;卷积神经网络&#xff0c;Convolution Neural Network 卷积计算公式&#xff1a;N &#xff08;W-F2p&#xff09;/s1 这个公式每次都得看看&#xff0c;不能忘 1 经典网络 按照时间顺序 1.1 LeNet LeNet是 Yann LeCun在1998年提出&#xff0c;用于解决手…

Ribbon:负载均衡及Ribbon

什么是负载均衡&#xff1f; 第一种轮询算法&#xff0c;依次遍历去执行&#xff0c;达到负载均衡 集成Ribbon 导入pom&#xff0c;在消费者服务里的pom文件导入 <!-- Ribbon 集成 --><!-- https://mvnrepository.com/artifact/org.springframework.cloud/spr…

《合成孔径雷达成像算法与实现》Figure3.12

clc clear close all% 参数设置 TBP 724; % 时间带宽积 T 42e-6; % 脉冲持续时间 t_0 1e-6; % 脉冲回波时延 Nfft 2^11; % fft长度% 参数计算 B TBP/…

第8步---MySQL的存储过程和触发器

第8步---MySQL的存储过程和触发器 1.存储过程 5开始支持的 sql集&#xff0c;类似Java中的代码中的方法 实现对sql的封装和服用 有输入和输出 可以声明变量 可以实现一下复杂的控制语句 1.1入门案例 基本语法 测试数据 -- 创建表的测试数据 create table dept(deptno int pri…

jstack(Stack Trace for Java)Java堆栈跟踪工具

jstack&#xff08;Stack Trace for Java&#xff09;Java堆栈跟踪工具 jstack&#xff08;Stack Trace for Java&#xff09;命令用于生成虚拟机当前时刻的线程快照&#xff08;一般称为threaddump或者javacore文件&#xff09;。 线程快照就是当前虚拟机内每一条线程正在执…

Linux:iptables SNAT与DNAT

目录 一、SNAT 1.1 SNAT原理与应用 1.2 SNAT转换前提条件 1.3 SNAT工作原理 1.4 SNAT实例 二、DNAT 2.1DNAT原理与应用 2.2 DNAT转换前提条件 2.2实例 一、SNAT 1.1 SNAT原理与应用 SNAT 应用环境:局域网主机共享单个公网IP地址接入Internet (私有IP不能在Internet中正…

JAVAEE免费工程师教程之springboot综合案例

day04_springboot综合案例 用户管理 查询用户 查询所有用户执行流程 编写UserMapper接口 public interface UserMapper {// 查询所有用户List<UserInfo> findAllUsers(); }编写UserService public interface UserService extends UserDetailsService {/*** 查询所有…

(2023,UniversalFakeDetect)跨生成模型泛化的通用假图像检测器

Towards Universal Fake Image Detectors that Generalize Across Generative Models 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. 相关工作 3. 基础 3.1 问题设置 3.2 分析为什么先前的工作无法泛化 4. 方法 5. 实验 5.1 研究生成模型 5.2 真假分类基线 5.3 …

三重奏的和谐:如何完美对齐公司、部门与个人目标

引言 在企业的运营和管理中&#xff0c;目标的设定与对齐是至关重要的。它不仅决定了公司的方向和愿景&#xff0c;还影响到每一个部门和团队成员的工作内容和效果。如何确保公司目标、部门目标和团队个人目标之间的完美对齐&#xff0c;是每一个管理者都需要面对的挑战。 目…

HCIP学习--STP

在交换机上的线路冗余会产生的问题 昨天讲到了一个冗余的概念&#xff0c;下面就这个冗余引出来的问题来记录今天的内容 线路的冗余对于路由器来岁意味择可以选择更多的路线&#xff0c;但是对于交换机来说可不是啥好事情 比如下图假设A下面有一台设备要发送一个广播&#x…

第二讲:BeanFactory的实现

BeanFactory的实现 1. 环境准备2. 初始化DefaultListableBeanFactory3. 手动注册BeanDefinition4. 手动添加后置处理器5. 获取被依赖注入的Bean对象6. 让所有的单例bean初始化时加载7. 总结 Spring 的发展历史较为悠久&#xff0c;因此很多资料还在讲解它较旧的实现&#xff0c…

ROS与STM32通信(二)-pyserial

文章目录 下位机上位机自定义msg消息发布订阅 ROS与STM32通信一般分为两种&#xff0c; STM32上运行ros节点实现通信使用普通的串口库进行通信&#xff0c;然后以话题方式发布 第一种方式具体实现过程可参考上篇文章ROS与STM32通信-rosserial&#xff0c;上述文章中的收发频率…

一例Vague病毒的分析

这是一例通过U盘传播的文件夹病毒&#xff0c;有收集用户文件的行为&#xff0c;但是&#xff0c;没有回传和远控行为&#xff0c;有点奇怪&#xff0c;其中的字符串进行了加密。 样本比较简单&#xff0c;使用IDA很容易就看明白了。 根据匹配到威胁情报&#xff0c;有叫Vague蠕…

阿里云服务器和轻量云服务器对比有什么区别?

阿里云轻量应用服务器和云服务器ECS有什么区别&#xff1f;ECS是专业级云服务器&#xff0c;轻量应用服务器是轻量级服务器&#xff0c;轻量服务器使用门槛更低&#xff0c;适合个人开发者或中小企业新手使用&#xff0c;可视化运维&#xff0c;云服务器ECS适合集群类、高可用、…