面试手撕代码
给定一个正整数n,一个集合A, A中数字0~9,求用A中数字组成的小于n的最大数,例如n=258, A={2,5,8},输出255
def findmax(n, nums):
if len(nums) == 0:
return None
nums = list(nums)
nums.sort()
len_nums = len(nums)
strn = [int(item) for item in str(n)]
len_n = len(strn)
max_list = [] # 存储对应数字在nums中的索引,方便回溯
i = 0
while i < len_n:
j = 0
while strn[i] >= nums[j]:
j += 1
if j >= len_nums:
break
if j == 0 and strn[i] < nums[j]:
# 在此种情形时,找不到小于strn[i]的数,如果max_list中存在i-1数,则将第i-1位置的索引j要减去1,如果j==0, 则将此数字从max_list中删除
if len(max_list) > 1 and max_list[i] > 0:
max_list[i] -= 1 # 如果max_list[i]正好等于0,那么其值为-1,后面依照索引生成数字时,直接删除
i -= 1 # i要回溯一个值
break
else:
max_list.append(j-1)
i += 1
# 存在一个极端情况,即最值与n相等,则要按位往前回溯,需要从最低位往前回溯,直至出现按位小于n对应数字的情况
if i == len_n and nums[max_list[-1]] == strn[-1]:
m = len_n-1
while m >= 0 and max_list[m] == 0:
del max_list[m]
m = m-1
if m == -1:
i = 0
else:
max_list[m] -= 1
i = m
# [i+1:len_n]用nums[-1]最值填充
max_num = []
for item in max_list:
if item >= 0:
max_num.append(nums[item])
for _ in range(i+1, len_n):
max_num.append(nums[-1])
if len(max_num) == 0:
return None
max_num = int("".join([str(item) for item in max_num]))
return max_num
思路比较混乱,从高位查找第一个小于位,只有用A中最值填充,若出现极端情况则要求往前回溯;若最后与n值相同,则要从最低位往前回溯查找。