字节社招一面算法记录

题目:给定一个数字n和数组numbers,求由numbers中元素组成的不大于n的最大数

思路:为了保证最终结果ans最大,需要尽量保证ans的高位和n的高位一致,ans的低位小于n的低位,这里存在三个需要注意的点

  1. numbers中不存在小于等于n最高位的数字,此时需要使用numbers中最大数,组成一个位数小于n的数字
  2. 对于n中某一位数,numbers中不存在小于等于该数的数字,那么该数的高位就需要小于n中对应数位的数
  3. 对于当高位存在了ans小于n的情况时,后续低位需要填充numbers中最大数

代码:

def func(n, numbers):
    """
    :param n: 整数n
    :param numbers: 0-9的number组成的数组
    :return: 由numbers中元素组成的不大于n的最大数
    """
    n_list = [int(i) for i in list(str(n))]
    numbers.sort()
    n_set = set(n_list)

    # cache 用于存储numbers中小于等于n中数字的元素
    cache = {}
    for num in n_set:
        left = 0
        right = len(numbers)-1
        while left <= right:
            mid = (left+right)//2
            if numbers[mid]>num:
                # right右侧的都大于num
                right = mid-1
            else:
                # numbers[mid]<=num,left左侧的都小于等于num
                left = mid+1
        cache[num] = numbers[:left]
    print(cache)

    def dfs(n_index):
        """
        #n_index表示位数
        #返回None:表示低位无法更小,高位需要减小
        #返回列表:表示低位拼出了更小的值
        """

        # 超出了位数 或者 numbers中所有值均大于该位数,那么必须高位使用较小值
        if n_index == len(n_list) or not cache.get(n_list[n_index]):
            return None
        # temp为numbers中小于该位数的所有元素,升序排列
        temp = cache[n_list[n_index]]
        # 当该数位在numbers中存在相等元素时,尝试让低位更小
        if temp[-1] == n_list[n_index]:
            rest = dfs(n_index + 1)
            if rest:
                return [temp[-1]]+rest
            else:
                # 低位无法更小时,尝试将本位修改为小于本位的最大值
                for index in range(1, len(temp)+1):
                    if temp[-index]<n_list[n_index]:
                        return [temp[-index]]
                # 本位也无法减小时,返回None,让高位尝试减小
                return None
        else:
            # 本位无法找到相等元素,选取小于本位的最大值,后续低位使用Numbers最大值填充
            return [temp[-1]]

    ans_list = dfs(0)

    ans = 0
    if not ans_list:
        # ans_list为None表示,numbers中不存在元素,小于等于n的最高位,此时减小ans的位数
        for i in range(len(n_list)-1):
            ans = ans*10+numbers[-1]
    else:
        for number in ans_list:
            ans = ans*10+number
        # 高位已经存在减小,低位填充number中的最大元素
        for _ in range(len(n_list) - len(ans_list)):
            ans = ans*10+numbers[-1]
    return ans

面试的时候思路错误写了错误的算法,面试结束后才发现写错了,不知道现在的写法是否有误,如果有误请大家指出

#我的求职思考#
全部评论
感觉写成递归回溯+剪枝(排序,大于n return),就可以给过了吧
点赞 回复 分享
发布于 2024-05-04 10:15 上海
佬怎么样了 约二面了吗
点赞 回复 分享
发布于 2023-12-15 23:50 浙江
只给了一题吗?还有其他题目不
点赞 回复 分享
发布于 2023-12-12 21:16 广东

相关推荐

头像 会员标识
09-13 21:41
已编辑
中南大学 C++
秋招好像还没结束,但对我来说已经差不多了。211本科985硕士,没论文,非科班出身,这几个标签凑在一起,大概就不该妄想挤进算法岗。想想自己真是走错了好多路。高中搞信息竞赛,大学继续打ACM,虽然最后只是区域赛打铁水平,零零星星只能拿几个蓝桥杯国奖。本科不是计算机专业,靠着那点竞赛底子,保研时也没能挤进985的科班。还被现在被导师忽悠了。他说搞人工智能,我以为是CV/NLP,结果他说的AI是遥感图像处理用的ANN。实验室的服务器甚至有的没有显卡,导师连Python环境都不会配置,整天嚷嚷让学生标注数据。暑假那会儿面C++开发还挺顺利,拿了五六家大厂offer。阴差阳错去做了算法实习,因为时间问题也没能转正。那时候听说AI&nbsp;infra是个方向,想着大模型推理总需要写C++的人吧,就把简历项目都往这个方向靠。问过业内前辈,说技术栈确实相通。还是太天真了。八月底才开始投简历,各大厂连面试都不给。笔试倒是发了一些,大部分都能AK,但做完就石沉大海。总共就面了不到五家公司,全是小厂,倒是给了offer,但总觉得差口气。研究生读得本就痛苦,导师PUA,毕业要求还高。抑郁吃了一年的药才康复。有时候半夜改简历,看着项目经历里那些自己捣鼓的推理优化,忽然觉得可笑——可能我这种半路出家的,本来就不该碰瓷算法岗。可能最难受的是,明明高中就开始写代码,写了这么年算法题,最后连个面试机会都挣不到。导师还在催毕业论文进度,而我连工作都没定下来。要是当初老老实实去做开发就好了。要是没被导师忽悠就好了。要是早点认清自己不是搞算法的料就好了。也许明年春招该回去投C++开发了。只是偶尔还会想起,在实习公司跑通第一个模型的那天下午,显示器里的loss曲线一直在下降,就像我的人生曲线一样,不知道什么时候才能收敛。可惜没要是。
你的秋招简历被谁挂了?
点赞 评论 收藏
分享
评论
2
13
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务