[英雄星球七月集训LeetCode解题日报] 第7日 哈希表

日报

题目

一、 970. 强整数

链接: 970. 强整数

1. 题目描述

在这里插入图片描述

2. 思路分析
  • 分别枚举小于bound的x的次方结果、y的次方结果。
  • 最终贡献答案的结果一定是两边的卷积组合。
  • 不用担心复杂度,额外处理1,其余的数指数枚举会很快break。
    在这里插入图片描述
3. 代码实现
class Solution:
    def powerfulIntegers(self, x: int, y: int, bound: int) -> List[int]:
        h = set()
        g = set()
        if x == 1:
            h.add(1)
        else:
            for i in range(bound+1):
                if x**i > bound:
                    break            
                h.add(x**i)
        if y == 1:
            g.add(1)
        else:
            for i in range(bound+1):
                if y**i > bound:
                    break            
                g.add(y**i)
        
        ans = set()
        for i,j in product(h,g):
            if i +j <= bound:
                ans.add(i+j)
        return list(ans)

二、 914. 卡牌分组

链接: 914. 卡牌分组

1. 题目描述

在这里插入图片描述

2. 思路分析
  • 题目要求每组都是x张相同牌。
  • 显然k×x张相同牌可以分k组。
  • 我们对每种牌计数,然后取所有数的最大公倍数x,就是能分的最少n/x组,每组x张。
  • 计算到中途如果公倍数为1了就可以提前退出。
  • 因此一个简单的优化:从小到大排序,公倍数更有可能提前降低。
  • 在这里插入图片描述
3. 代码实现
class Solution:
    def hasGroupsSizeX(self, deck: List[int]) -> bool:
        cnt = Counter(deck)
        vs = sorted(list(cnt.values()))
        g = vs[0]
        for i in range(1,len(vs)):
            g = gcd(g,vs[i])
            if g == 1:
                return False
        return g>1

三、 1497. 检查数组对是否可以被 k 整除

链接: 1497. 检查数组对是否可以被 k 整除

1. 题目描述

在这里插入图片描述

2. 思路分析

这题可以无脑的分类讨论:

  • 首先每对里第一个数如果模k=a,则另一个数一定需要模k=k-a;
  • 因此用m计数买个数字出现的次数,然后分配即可。
  • 特别的:
    • 如果模k0,则只能安排同样模k0的数字一组,因此这组判是否是偶数。
    • 如果模k==i,则只能安排k-i,判断两种数是否一样多。
    • 如果模k==自己,比如4模8还是4,只能安排同样的数字一组,因此判断是否是偶数。
  • 那么我们计数完处理每种模的数字数量即可,复杂度O(n)+O(k)
3. 代码实现
class Solution:
    def canArrange(self, arr: List[int], k: int) -> bool:
        m = [0] * k 
        for a in arr:
            m[a%k] += 1
        if m[0] & 1:
            return False
        for i in range(1,k):
            if k - i  == i:
                if m[i] & 1:
                    return False 
            else:
                if m[i] != m[k-i]:
                    return False
        return True

四、 面试题 17.05. 字母与数字

链接: 面试题 17.05. 字母与数字

1. 题目描述

在这里插入图片描述

2. 思路分析
  • 先预处理数组,字母记-1,数字记1,题目转化为求子段和为0的最长子段。
  • 由于是连续的,我们先前缀和优化。
  • 那么我们遍历前缀和数组时,对于每个presum[i],需要找一个前边的j,使presum[i]-presum[j]==0;
  • 即presum[i]==presum[j]。那么用哈希表记录下每个值的第一次出现即可。
  • 字段长度k=i-j,对应的更新k和答案的左端点j。最后输出原数组对应位置子段即可。
  • 特殊的,0第一次出现位置应该是-1。
    在这里插入图片描述
3. 代码实现
class Solution:
    def findLongestSubarray(self, array: List[str]) -> List[str]:   
        if len(array) <= 1:
            return []     
        t =  [1 if a.isdigit() else -1 for a in array]  # 预处理t,题目转化为求t中和为0的最长子段。
        # print(t)
        presum = list(accumulate(t))
        # print(presum)
        d = {0:-1}
        k = 0
        ans = 0
        for i,s in enumerate(presum):
            if s in d:
                pre = d[s]
                if i - pre > k:
                    k = i - pre 
                    ans = pre 
            else:
                d[s] = i 
        # print(ans,k)
        return array[ans+1:ans+1+k] if k else []
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值