📅  最后修改于: 2023-12-03 14:50:38.284000             🧑  作者: Mango
在给定一个最多由0和7组成的长度为N的数字集合中,寻找最大的能够被50整除的数。
首先,我们需要清楚一个性质:一个数能被50整除,当且仅当它能被10整除,并且它的个位上是0。于是,我们可以从高位到低位扫描这个数字集,每一位的选择只有0或者7,如果选择了7,则要求前面的数字模10余3,如果选择了0,则不限制前面数字的余数。最后得到的数一定是能被50整除的最大数。
时间复杂度:$O(2^N)$
如果一个数能被50整除,那么它一定能被10和25整除,所以我们只需要找一个长度为N的由0和7组成的序列,并且这个序列末尾连续的两个数字组成的数能被4整除(因为25能被4整除)即可。不妨假设这个序列的长度为k,那么我们只需要在这个序列中找到一个尽可能长的子序列,使得它末尾的两个数字组成的数能被4整除。对于长度为k的序列,末尾两个数能组成的数字共有8种,分别是00、04、07、14、17、20、24、27。我们可以用一个长度为8的桶记录每一种数字组合的最长子序列长度,然后从桶的末尾向前遍历,取长度最长的子序列作为答案。
时间复杂度:$O(N)$
def max_num(N):
if N == 1:
return 0
ans = -1
for i in range(2 ** N):
flag = True
num = 0
for j in range(N):
if i & (1 << j):
num = num * 10 + 7
if num % 10 != 3:
flag = False
break
else:
num = num * 10
if flag and num % 50 == 0:
ans = max(ans, num)
return ans
def max_num(N):
if N == 1:
return 0
cnt = [0] * 8
for i in range(2 ** N - 1, -1, -1):
num = 0
for j in range(N):
if i & (1 << j):
num = num * 10 + 7
else:
num = num * 10
if num % 4 == 0:
idx = (num % 100) // 10 * 4 + num % 4
cnt[idx] = max(cnt[idx], bin(i).count('1'))
ans = 0
for i in range(8):
if cnt[i] > 0:
num = i // 4 * 10 + i % 4
ans = ans * (2 ** cnt[i]) + num * (10 ** cnt[i])
return ans
两种方法分别适用于不同情况。当N比较小的时候,暴力枚举的时间复杂度并不高,可以使用方法1;当N比较大时,可以使用方法2进行数学分析,优化时间复杂度。