【秋招笔试复盘】秋招的第一场笔试——网易

第二题

题目:给定一个字符串,只包括r,e,d求子字符串的数量,要求该子字符串中r,e,d都出现且出现的次数相同。
例子:rrededrde
输出:4
解释:r[red]edrde, rred[edr]de, r[rededr]de, rreded[rde]
关键考点:动态哈希+差异状态设计

思路

  • 暴力法:
    枚举左右端点,统计区间内的r、e、d字符个数。o(n^3)
  • 暴力优化:
    区间的字符个数可用前缀和之差获得。o(n^2)
  • dp大法:
    用map维护所有以i为结尾的子字符串的统计情况,位置i+1的更新规则为:在map中搜索所有加入第i+1个字符串后满足题意的子字符串个数并累加到答案中,然后根据该字符更新map中的所有字符串统计情况,更新得到以i+1为结尾的子字符串的统计情况。
    更新map比较费时,最差情况下也是o(n^2)
  • o(n)解法:
    如果我们知道当前位置3⃣️的前缀和(3,2,2),则我们要去找前面有多少个前缀和为(2,1,1)或者(1,0,0)的,例如图中的位置1⃣️和位置2⃣️,都能使以位置3⃣️为区间右端点内的r、e、d的个数相等。很自然的我们可以在从左至右的遍历过程中用map维护所有的前缀和,但这样做在对当前位置查找左端点时要枚举很多种r、e、d的统计情况。例如若当前前缀为(4,3,3),则需在map中get(3,2,2)、(2,1,1)、(1,0,0)。我们发现实际上我们并不在乎r、e、d的绝对个数是多少,我们实际关注的是他们之间个数的差异。(4,3,3)、(3,2,2)、(2,1,1)、(1,0,0)都能统一表示为r、e、d相对于r的个数(0,-1,-1)。所以在做前缀时,我们直接记录并保存差异即可。只需遍历一遍,时间复杂度为o(n)。
    在这里插入图片描述
from collections import defaultdict

string = 'rrededrde'
n = len(string)
pre_map = defaultdict(int)
cnt = defaultdict(int)
ans = 0
for i in range(n):
    cnt[string[i]] += 1
    r_cnt, e_cnt, d_cnt = cnt['r'], cnt['e'], cnt['d']
    pre = f'{0}_{e_cnt-r_cnt}_{d_cnt-r_cnt}'
    ans += pre_map[pre]
    pre_map[pre] += 1
print(ans)

ps:其实dp大法和最优解法思想差不多,只不过dp法是通过更新dp的值来保持其时效正确性,而最优法是采取丢入map的技巧,减少维护的代价。

第三题

n, k = map(int, input().split())
nums = list(map(int, input().split()))
# 2**30
nums_bina = [[0]*30 for _ in range(n)]
for i, num in enumerate(nums):
    bina = list(map(int, bin(num)[2:][::-1]))
    for j in range(len(bina)):
        nums_bina[i][j] += bina[j]
i = 29
ans = [0]*29
def dfs(i, k, nums, nums_bina):
    if i < 0: return
    if sum(nums_bina[j][i] for j in range(len(nums))) == k:
        res = 2**29 -1
        for j in range(len(nums)):
            if nums_bina[j][i] == 1:
                res &= nums[j]
        bina = list(map(int, bin(res)[2:][::-1]))
        for k in range(i):
            ans[k] = bina[k]
        return
    elif sum(nums_bina[j][i] for j in range(len(nums))) > k:
        nums_ = []
        nums_bina_ = []
        for j in range(len(nums)):
            if nums_bina[j][i] == 1:
                nums_.append(nums[j])
                nums_bina_.append(nums_bina[j])
        ans[i] = 1
        dfs(i-1, k, nums_, nums_bina_)
    else:
        dfs(i-1, k, nums, nums_bina)

dfs(29, k, nums, nums_bina)
ans_out = 0
for i in range(len(ans)):
    if ans[i]:
        ans_out += 2 ** i
print(ans_out)
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值