笔试算法-编程练习-01-X-23

m这套题包含一道基础题,一道贪心。基础题应该都可以AC,贪心比较考验发现规律的能力。


一、手机流畅运行的秘密

题目描述

8 月份发布会一结束,米小兔就在公司领到了一台最新发布的 Xiaomi MIX Fold 3 手机,这是一款小米旗舰折叠屏手机,并搭载了全新升级架构的 MIU114 系统。其先进的应用引擎不仅让系统更流畅,应用体验也大幅提升。 在一个优化项中,为了尽可能提升用户白天使用手机的体验和续航,某些已经在系统中注册过的任务会被设置为空闲任务,仅在手机空闲时运行 (比如数据备份或 AI 相册整理)。

现在系统中注册了若干组空闲任务,每个任务有各自的耗电量以及允许任务运行的最低初始电量,我们需要计算手机能够串行完成全部任务的最低初始电量。

注意点1: 所有电量以 mAh(毫安时)计,Xiaomi MIX Fold 3 的大电池容量是4800mAh。

注意点2: 本题目假设手机在运行空闲任务期间,不处于充电状态,也没有额外耗电行为。

注意点3: 智能应用引擎会以最合适的顺序串行运行任务。

输入描述

一个描述了所有任务的长字符串。任务与任务之间用逗号隔开,每组任务由耗电量及最低初始电量组成,用冒号隔开。

输出描述

一个数字,代表依次完成全部任务的最低初始电量,如果最低初始电量超过手机电池容量,则返回-1。

输入示例
1:10,2:12,3:10
输出示例
13
提示信息

在样例中,手机至少需要有 13mAh 的初始电量,在运行任务 2 后剩余电量 11mAh、运行任务1后剩余电量 10mAh、运行任务 3 后剩 7 mAh。

题目分析:

这个题目很显然是贪心,但是找到贪心的根据还是有难度的。本题的核心是优先执行剩余电量最大的任务,这样才能保证余量最大,才有可能以较小的代价执行 初始电量需求较高的任务。

我目前做贪心的题目还没发现什么方法论,主要是还是看当时的状态,想到了就做出来了,想不到就没办法,大家要是有什么思考的方法可以一起讨论一下。

确定贪心的方向后面就好做了,但是需要注意组织好自己的数据结构,我这里是采用了一个双层字典,第一层的key是执行完本任务的余电,第二层的key是本任务需要的初始电量,value是个list,表示符合上述约束的任务的耗电量。(大家可以参考,其他方式应该也可以)

在执行过程中,优先执行余电多的,二级优先执行初始电量需要高的。

字节23年的【扑克牌同花顺】这道题与本题类似,可以参考23年字节笔试-0820-CSDN博客

代码:

temp = input().split(',')
jobs = {}
for t in temp:
    t = t.split(':')
    a, b = int(t[0]), int(t[1])
    rest = b-a
    
    if rest in jobs.keys():
        if b in jobs[rest].keys():
            jobs[rest][b].append(a)
        else:
            jobs[rest][b] = [a]
    else:
        jobs[rest] = {b:[a]}


def calc(jobs):
    KEYS = sorted(jobs.keys())[::-1]
    result = 0
    current = 0
    for k in KEYS:
        b = sorted(jobs[k].keys())[::-1]
        for j in b:
            for a in jobs[k][j]:
                if current < j:
                    result += j-current
                    if result > 4800:
                        return -1
                    current = j
                current -= a
    return result
    
print(calc(jobs))

二、小米手机通信校准

题目描述

小米手机生产过程中会经过严苛的测试环节,其中包括手机通讯功能中的射频校准。射频校准会打点数据上报到云端。 

其中包含两组数据:第一组数据中会包含此次校准的频道号(freq)信息;第二组会上传一批数据,包含一组频道号(freg)和其对应的损失值(loss),其中这一组频道号(freg)不会重复,且是有序的。 

现在需要根据第一组数据中的频道号(freg),找到离第二组中频道号(freq)最近的那个freq对应的loss值,如果两边一样近,则取两边loss的平均。 注:输入为int,输出为double类型四舍五入保留1位小数

输入描述

包含两组数据: 

第一组数据中会包含此次校准的频道号(freq)信息。 

第二组会上传一批数据,包含一组频道号(freg)和其对应的损失值(loss),其中这一组频道号(freg)不会重复,且是有序的。

输出描述

离频道号(freq)最近的freq对应的loss值,如果两边一样近,则取两边loss的平均。

输入示例
2800
1950:10 2000:15 3000:9
输出示例
9.0

题目分析:

这道题比较简单,就是已知目标值,在升序数组中寻找最接近的值,遍历即可。

代码:

f1 = int(input().split()[0])
temp_in = input().split(' ')

def calc(f1, temp_in):
    dis = 1000000000
    for idx in range(len(temp_in)):
        t_in = temp_in[idx]
        temp = t_in.split(':')
        f, loss = int(temp[0]), float(temp[1])
        
        temp_dis = abs(f1-f)
        if dis > temp_dis:
            dis = temp_dis
        elif dis == temp_dis:
            last_loss = float(temp_in[idx-1].split(':')[1])
            return (last_loss + loss)/2
        else:
            last_loss = float(temp_in[idx-1].split(':')[1])
            return last_loss
    return float(temp_in[-1].split(':')[1])

print(calc(f1, temp_in))

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值