zoukankan      html  css  js  c++  java
  • 哈希表相关题目-python

    栈&队列&哈希表&堆-python  https://blog.csdn.net/qq_19446965/article/details/102982047

    1、O(1)时间插入、删除和获取随机元素

    设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。

    insert(val):当元素 val 不存在时,向集合中插入该项。
    remove(val):元素 val 存在时,从集合中移除该项。
    getRandom:随机返回现有集合中的一项。每个元素应该有相同的概率被返回。
    示例 :

    // 初始化一个空的集合。
    RandomizedSet randomSet = new RandomizedSet();

    // 向集合中插入 1 。返回 true 表示 1 被成功地插入。
    randomSet.insert(1);

    // 返回 false ,表示集合中不存在 2 。
    randomSet.remove(2);

    // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
    randomSet.insert(2);

    // getRandom 应随机返回 1 或 2 。
    randomSet.getRandom();

    // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
    randomSet.remove(1);

    // 2 已在集合中,所以返回 false 。
    randomSet.insert(2);

    // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
    randomSet.getRandom();

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/insert-delete-getrandom-o1

    class RandomizedSet(object):
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self.nums = []
            self.maps =  {}     
    
        def insert(self, val):
            """
            Inserts a value to the set. Returns true if the set did not already contain the specified element.
            :type val: int
            :rtype: bool
            """
            if val in self.maps:
                return False
            
            self.nums.append(val)
            self.maps[val] = len(self.nums) - 1
            return True 
    
        def remove(self, val):
            """
            Removes a value from the set. Returns true if the set contained the specified element.
            :type val: int
            :rtype: bool
            """
            if val not in self.maps:
                return False
    
            # 将末尾的值移到待删除元素的位置
            index = self.maps.get(val)
            last_val = self.nums[-1]
            self.nums[index] = last_val
            self.maps[last_val] = index
            # 删除最后一个元素
            self.nums.pop() 
            # 删除被删除元素的index
            del self.maps[val]
            return True
            
        def getRandom(self):
            """
            Get a random element from the set.
            :rtype: int
            """
            return random.choice(self.nums)

    2、O(1) 时间插入、删除和获取随机元素 - 允许重复

    示例:

    // 初始化一个空的集合。
    RandomizedCollection collection = new RandomizedCollection();

    // 向集合中插入 1 。返回 true 表示集合不包含 1 。
    collection.insert(1);

    // 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
    collection.insert(1);

    // 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
    collection.insert(2);

    // getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
    collection.getRandom();

    // 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
    collection.remove(1);

    // getRandom 应有相同概率返回 1 和 2 。
    collection.getRandom();

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/insert-delete-getrandom-o1-duplicates-allowed

    1)把某个数在数组中出现的所有的位置用dict的形式存储下来

    2)重复元素用set存下来,用于判断

    3)删除一个数的时候,就是从这个 list 里随便拿走一个数(比如最后一个数)

    class RandomizedCollection(object):
    
        def __init__(self):
            """
            Initialize your data structure here.
            """
            self.nums = []
            self.maps = collections.defaultdict(set)
    
        def insert(self, val):
            """
            Inserts a value to the collection. Returns true if the collection did not already contain the specified element.
            :type val: int
            :rtype: bool
            """
            self.nums.append(val)
            self.maps[val].add(len(self.nums)-1)
            return len(self.maps[val]) == 1
            
    
        def remove(self, val):
            """
            Removes a value from the collection. Returns true if the collection contained the specified element.
            :type val: int
            :rtype: bool
            """
            if not self.maps[val]:
                return False
            
            index = self.maps[val].pop()
            self.nums[index] = None
            return True
    
        def getRandom(self):
            """
            Get a random element from the collection.
            :rtype: int
            """
            x = None
            while x is None:   # 注意:这里不能写成while not x:
                x = random.choice(self.nums)
            return x
    

    3、 复制带随机指针的链表

    给定一个链表,每个节点包含一个额外增加的随机指针,该指针可以指向链表中的任何节点或空节点。

    要求返回这个链表的深拷贝。 

    示例:

    输入:
    {"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}

    解释:
    节点 1 的值是 1,它的下一个指针和随机指针都指向节点 2 。
    节点 2 的值是 2,它的下一个指针指向 null,随机指针指向它自己。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/copy-list-with-random-pointer

    首先,先复习一下正常链表的拷贝:

    class Node(object):
        def __init__(self, val, next, random):
            self.val = val
            self.next = next
            self.random = random
    

      

    def copy_list(head):
        if not head:
            return None
    
        new_head = Node(head.val)
        p = head
        q = new_head
        while p:
            if p.next:
                q.next = Node(p.next.val)
            else:
                q.next = None
            p = p.next
            q = q.next
        
        return new_head
    

    此题还要存储一下random节点

    class Solution(object):
        def copyRandomList(self, head):
            """
            :type head: Node
            :rtype: Node
            """
            if head == None:
                return None
    
            maps = {}
            new_head = Node(head.val, None, None)
            maps[head] = new_head
            p = head
            q = new_head
            while p:
                q.random = p.random
                if p.next:
                    q.next = Node(p.next.val, None, None)
                    maps[p.next] = q.next
                else:
                    q.next = None  
                p = p.next
                q = q.next
                
            p = new_head
            while p:
                if p.random:
                    p.random = maps.get(p.random)
                p = p.next
            
            return new_head
    

    4、 乱序字符串

    给出一个字符串数组S,找到其中所有的乱序字符串(Anagram)。如果一个字符串是乱序字符串,那么他存在一个字母集合相同,但顺序不同的字符串也在S中。

    所有的字符串都只包含小写字母

    样例1:

    输入:["lint", "intl", "inlt", "code"]
    输出:["lint", "inlt", "intl"]
    

    样例 2:

    输入:["ab", "ba", "cd", "dc", "e"]
    输出: ["ab", "ba", "cd", "dc"]

    什么是Anagram?

    • 如果在更改字符顺序后它们可以相同,则两个字符串是anagram。

    链接:https://www.lintcode.com/problem/anagrams/description

    class Solution:
        """
        @param strs: A list of strings
        @return: A list of strings
        """
        def anagrams(self, strs):
            # write your code here
            maps = collections.defaultdict(list)
            for word in strs:
                char_list = ''.join(sorted(word))
                maps[char_list].append(word)
            res = []
            for word_list in maps.values():
                if len(word_list) >= 2:
                    res += word_list
            return res
    

    5、最长连续序列

    给定一个未排序的整数数组,找出最长连续序列的长度。

    要求算法的时间复杂度为 O(n)。

    示例:

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

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/longest-consecutive-sequence

    第一种:O(nlogn)

    先排序,再统计

    class Solution(object):
        def longestConsecutive(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            if len(nums) <= 1:
                return len(nums)
    
            nums.sort()
            length = 1
            sum = 1
            for i in range(1, len(nums)):
                if nums[i] - nums[i-1] == 0:
                    continue
                
                if nums[i] - nums[i-1] == 1:
                    sum += 1
                else:
                    if sum > length:
                        length = sum
                    sum = 1
                    
            if sum > length:
                length = sum
            return length
    

    第二种:O(n)

    HashSet 判断

    class Solution(object):
        def longestConsecutive(self, nums):
            """
            :type nums: List[int]
            :rtype: int
            """
            maps = set(nums)
            length = 0
        
            for num in nums:
                if num in maps:
                    sum = 1
                    maps.remove(num)
                    l = num - 1
                    r = num + 1
                    while l in maps:
                        maps.remove(l)
                        l -= 1 
                        sum += 1
                    while r in maps:
                        maps.remove(r)
                        r += 1
                        sum += 1
                    if length < sum:
                        length = sum
                        
            return length
    

      参考:九章算法讲解 https://www.jiuzhang.com/solution/

  • 相关阅读:
    动态代理:JDK动态代理和CGLIB代理的区别
    spring启动component-scan类扫描加载,以及@Resource,postConstruct等等注解的解析生效源码
    spring启动component-scan类扫描加载过程---源码分析
    spring源码分析之spring-core asm概述
    Spring组件扫描 <context:component-scan/>
    【OSGI】1.初识OSGI-到底什么是OSGI
    superrvisor application config ini
    doris 0.9.0版本docker镜像制作与使用
    Docker系列09:搭建Harbor本地镜像仓库
    Docker系列08:容器监控
  • 原文地址:https://www.cnblogs.com/rnanprince/p/11878854.html
Copyright © 2011-2022 走看看