【LeetCode】基本数据结构

 

目录

注意:

1. 两数之和

187. 重复的DNA序列

706. 设计哈希映射

652. 寻找重复的子树

560. 和为K的子数组

547. 朋友圈

684. 冗余连接

692. 前K个高频单词

 


注意:

和大雪菜刷题https://www.bilibili.com/video/BV1T441167eG

1. 两数之和

思路:

  • 利用哈希表存储每个数字的下标。
  • 遍历数组的同时,检查哈希表里target-nums[i]是否存在,存在则返回答案
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = {}
        for index, num in enumerate(nums):
            if (target-num) in hashtable:
                return [hashtable[target-num], index]
            hashtable[num] = index

187. 重复的DNA序列

思路:

  • 注意题目要求是长度为10的子串
  • 这样只需用一个哈希表统计长度为10的子串出现的次数即可,>=2的结果进行保存。用前缀树也可以解决。
class Solution:
    def findRepeatedDnaSequences(self, s: str) -> List[str]:
        res = []
        hash_tabel = {}
        for i in range(len(s)-9):
            tmp = s[i:i+10]
            hash_tabel[tmp] = hash_tabel.get(tmp, 0) + 1
            if hash_tabel[tmp] == 2:
                res.append(tmp)
        return res

706. 设计哈希映射

思路:

  • 哈希主要会遇到冲突的问题:拉链法、开放寻址法
class MyHashMap:

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.hash = [[] for _ in range(20011)]  # 开辟一个大数组,长度为质数,注意这里不能用 [[]] * 20011
        # 一般定义成离2的整次幂比较远的质数,这样取模之后冲突的概率比较低。

    def put(self, key: int, value: int) -> None:
        """
        value will always be non-negative.
        """
        t = key % 20011
        for item in self.hash[t]:  # 遍历哈希到的链表中,查找key,并更新值
            if item[0] == key:
                item[1] = value
                return  # 更新完之后,直接返回
        self.hash[t].append([key, value])  # 如果链表中找不到对应的key,将其新添到链表中

    def get(self, key: int) -> int:
        """
        Returns the value to which the specified key is mapped, or -1 if this map contains no mapping for the key
        """
        t = key % 20011
        for item in self.hash[t]:
            if item[0] == key:
                return item[1]
        return -1  # 可能哈希的位置,所对应的链表不为空,但是不存在该值

    def remove(self, key: int) -> None:
        """
        Removes the mapping of the specified value key if this map contains a mapping for the key
        """
        t = key % 20011
        delete = []
        for item in self.hash[t]:
            if item[0] == key:
                delete = item  # remove方法,这里可以偷懒,把对应的value值设为-1,即表示它已经删除
        if delete:
            self.hash[t].remove(delete)

652. 寻找重复的子树

思路:

  • 进行遍历将子树转换成字符串再将每一个字符串转换成为数字
  • 拥有相同数字的子树则是重复的
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def __init__(self):
        self.hashtabel = {}
        self.count = {}
        self.cnt = 0
        self.ans = []

    def findDuplicateSubtrees(self, root: TreeNode) -> List[TreeNode]:
        self.cnt += 1
        self.hashtabel["#"] = self.cnt
        self.dfs(root)
        return self.ans
        

    def dfs(self, root):
        if not root:
            return str(self.hashtabel["#"])
        left = self.dfs(root.left)
        right = self.dfs(root.right)
        tree = str(root.val) + "," + left + "," + right
        if tree not in self.hashtabel:
            self.cnt += 1
            self.hashtabel[tree] = self.cnt
        t = self.hashtabel[tree]
        self.count[t] = self.count.get(t, 0) + 1
        if self.count[t] == 2:
            self.ans.append(root)
        return str(t)

560. 和为K的子数组

思路:

  • 这道题的关键就是前缀和+哈希
  • 假设S[i]是0~i的前缀和,那么i~j的和就是S[j]- S[i-1]
  • 题目的目标是寻找所有s[j]-s[i-1]==k的部分
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        hashtabel = {}
        hashtabel[0] = 1
        n = len(nums)
        acc,cnt = 0, 0
        for i in range(n):
            acc += nums[i]
            if acc-k in hashtabel:
                cnt += hashtabel[acc-k]
            if acc in hashtabel:
                hashtabel[acc] += 1
            else:
                hashtabel[acc] = 1
        return cnt

547. 朋友圈

思路:

  • 并查集主要的两部分就是(1.合并两个集合 2.判断两个点是否在同一个集合中)
class Solution:
    def findCircleNum(self, M: List[List[int]]) -> int:
        n = len(M)
        father = [0] * n
        for i in range(n):
            father[i] = i
        res = n
        for i in range(n):
            for j in range(i):
                if M[i][j]==0:
                    continue
                if self.find(i, father) != self.find(j, father):
                    father[self.find(i, father)] = self.find(j, father)
                    res -= 1
        return res
    
    def find(self, x, father):
        if father[x] != x:
            father[x] = self.find(father[x], father)
        return father[x]

684. 冗余连接

思路:

  • 使用并查集的思路,按顺序读取边集里的边,然后边里的点并入同一个集合之中
  • 若当前边的两端点已经在一个集合里了,则说明这条边是冗余的,直接返回
class Solution:
    def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
        n = len(edges)
        father = [0]*(n+1)
        for i in range(1, n+1):
            father[i] = i
        for edge in edges:
            a, b = edge[0], edge[1]
            if self.find(father, a) == self.find(father, b):
                return [a, b]
            father[self.find(father, a)] = self.find(father, b)
        
    def find(self, father, x):
        if father[x]!=x:
            father[x] = self.find(father, father[x])
        return father[x]

692. 前K个高频单词

思路:

  • 堆的特点(寻找最值O(1),增删查改O(logn))
class Solution:
    def topKFrequent(self, words: List[str], k: int) -> List[str]:
        count = collections.Counter(words)
        heap = [(-freq, word) for word, freq in count.items()]
        heapq.heapify(heap)
        return [heapq.heappop(heap)[1] for _ in range(k)]
        

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值