【转】一道Python面试题:不用 Python 自带的 Dict 实现自己的 HashTable

引言:这个题目其实源于很久之前的一次 Uber 面试,码工换工作无非就是刷 leetcode ,研究如何翻转二叉树之类的算法问题,所以头一次在电话里听到这道题的时候还是挺耳目一新的。当时顺利写出来了,也通过了电面,但觉得还是有不完善的地方,比如说代码不够 “Pythonic” 等,所以趁着周天晚上闲着无事,又拿出来写了写

HashTable 本身没啥好说的,中文叫”哈希表“或者”散列表“,这个数据结构用来存储”键-值“结构的数据,可以做到常数级时间复杂度的查找。
HashTable有两个问题需要解决,首先是key值哈希化,我们可以借助Python自带的hash函数解决key的哈希编码问题。其次是Hash 冲突的解决机制,在这里只考虑最简单的一种,即将同一个 hash 值下的不同的 key 存放在数组的同一个位置,以链表形式保存

class MyDict(object):
    
    def __init__(self, size=10000):
        # 用list初始化hashtable,并且每个位置都对应一个子list已解决hash冲突问题
        self.hash_list = [list() for _ in range(size)]
        self.size = size
        
    def __setitem__(self, key, value):
        # 利用python自带的hash函数,对key哈希并对size取模
        # hased_key位置没有值就追加,否则覆盖
        hashed_key = hash(key) % self.size
        for item in self.hash_list[hashed_key]:
            if item[0] == key:
                item[1] = value
                break
        else:
            self.hash_list[hashed_key].append([key, value])
            
    def __getitem__(self, key):
        # return: key所对应的value
        # 没有key,就抛出keyError
        
        for item in self.hash_list[hash(key) % self.size]:
            if item[0] == key:
                return item[1]
        raise KeyError(key)
        
    def __repr__(self):
        # hashtable打印
        result = []
        for sub_list in self.hash_list:
            if not sub_list:
                continue
            for item in sub_list:
                result.append(str(item[0]) + ": " + str(item[1]))
        return "{" + ", ".join(result) + "}"
    
    def __contains__(self, key):
        # 是否包含key,实现in操作符的功能
        for item in self.hash_list[hash(key) % self.size]:
            if item[0] == key:
                return True
        return False
    
    # 通过调用 keys() 、values() 、items() 来分别遍历键、值、键值对
    def __iterate_kv(self):
        for sub_list in self.hash_list:
            if not sub_list:
                continue
            for item in sub_list:
                yield item

    def __iter__(self):
        for kv_pair in self.__iterate_kv():
            yield kv_pair[0]

    def keys(self):
        return self.__iter__()

    def values(self):
        for kv_pair in self.__iterate_kv():
            yield kv_pair[1]

    def items(self):
        return self.__iterate_kv()
md = MyDict()
md
{}
md['a'] = 1
md['b'] = 2

md['a']
>>> 1
md['a'] = 3
md['a']
>>> 3
md['c']
---------------------------------------------------------------------------

KeyError                                  Traceback (most recent call last)

<ipython-input-15-274bae202805> in <module>()
----> 1 md['c']


<ipython-input-9-35e8cb6491bb> in __getitem__(self, key)
     24             if item[0] == key:
     25                 return item[1]
---> 26         raise KeyError(key)
     27 
     28     def __repr__(self):


KeyError: 'c'
md
>>> {a: 3, b: 2}

list(md.keys())
>>> ['a', 'b']
>
list(md.values())
>>> [3, 2]
>
list(md.items())
>>> [['a', 3], ['b', 2]]

'a' in md
>>>  True

md.__contains__('c')
>>> False

参考:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值