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

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

知识储备--基础算法篇-Hash table_第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

知识储备--基础算法篇-Hash table_第2张图片

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()]

知识储备--基础算法篇-Hash table_第3张图片

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_第4张图片

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

知识储备--基础算法篇-Hash table_第5张图片

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

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
        

知识储备--基础算法篇-Hash table_第6张图片

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函数

你可能感兴趣的:(散列表,哈希算法,数据结构)