算法笔试-编程练习-好题-01

经过之前的练习,我们已经基本熟悉了笔试中的常见题目,接下来我将过滤掉一些特别简单或者特别困难的题目,总结一些会了不难,但没见过可能一时间想不出来的好题。

本文中的好题包括:
1)如何判断两个数是否在一个等差数列中?同余!

2)贪心


P0001. 数组消除

题目内容

给定一个整数数组nums,同时给定一个整数interval。

指定数组nums中的某个元素作为起点,然后以interval 为间隔递增,如果递增的数(包含起点)等于nums中的元素,则数组nums中对应的元素消除,返回消除元素最多的起点元素。如果消除的元素同样多,则返回最小的起点元素。

输入描述

输入格式:

第一行输入整数数组的长度n

第二行输入长度为nn的整数数组nums

第三行输入整数interval

输出描述

起点元素的最小值

样例1

输入

6
4 5 7 1 1 2
3

输出

1

题目分析:

【题目类型:数学、同余、等差数列】

可以被消除的数字都位于,差为interval的等差数列上,那么如何确定两个数字是否位于该等差数列上呢?同时对于interval取余,余数相等,则位于同一个等差数列上,这就是同余。这个余数就是这个序列的标识。那么我们使用字典实时更新当前序列的中最小值和数字的数量即可。

考察发现数学规律的能力、数据结构的组织能力。

代码:

n = int(input())
nums = [int(i) for i in input().split()]
ans = {}
interval = int(input())

for i in nums:
    k = i%interval
    if k in ans:
        ans[k]['cnt'] += 1
        if i < ans[k]['re']:
            ans[k]['re'] = i
    else:
        ans[k] = {
            'cnt': 1,
            're': i
        }

cnt = 0
result = 10000000
for k in ans.keys():
    if ans[k]['cnt'] > cnt:
        cnt = ans[k]['cnt']
        result = ans[k]['re']
    elif ans[k]['cnt'] == cnt and result > ans[k]['re']:
        result = ans[k]['re']
print(result)

P0002. 参会

题目内容

有n场编号从0到n−1的博览会将要举办,编号为i的博览会举办时间为[starti,endi],即从第start天到第end天,包含第start​天和第end天。

小塔计划参加这些博览会,每天最多可以参加kk场博览会。请问小塔最多可以参加多少场博览会。需注意,小塔不需要全程参加一场博览会,只需要在某一天参加即可。

输入描述

第一行输入包含两个整数n和k,n表示博览会的数量,k表示每天最多可以参加的博览会的数量。以下n行每行包含两个整数starti​和endi​,表示第i场博览会的举办时间。

输出描述

小塔最多能参加的博览会数量。

样例1

输入

3 1
1 2
2 3
1 1

输出

3

题目分析

【题目类型:贪心】

一直觉得贪心是比较难的一类题目,遇到一些难题的时候容易出现明确知道用贪心但想不出来如何贪心的问题。比较好的练习方式就是见多识广。

这道题的贪心思想就是,优先参加快结束了的会议,这点想明白了,这题就变成了一道模拟题。更优秀的做法可以结合优先队列,但是下面的代码也能全部AC。

代码:


# 获取输入
n, k = map(int, input().split())
meetings = {}
for m in range(n):
    s, e = map(int, input().split())
    if s in meetings.keys():
        meetings[s].append(e)
    else:
        meetings[s] = [e]


ans = 0
startDay = sorted(meetings.keys())  # 按顺序遍历每一天
while len(startDay)>0:
    day = startDay.pop(0)

    if len(meetings[day]) <= k:
        ans += len(meetings[day])   # 该天的会议数量不够k,就全用了
    else:
        # 会议数量大于k,则参加end排序前k的会议
        ans += k
        meetings[day] = sorted(meetings[day])
        idx = k
        while idx < len(meetings[day]):   # 并且去掉当天结束的会议
            if meetings[day][idx] > day:
                break
            idx += 1
        
        # 如果仍有会议,则推到下一天
        if idx < len(meetings[day]):
            if day+1 in meetings.keys():
                meetings[day+1] += meetings[day][idx:]
            else:
                meetings[day+1] = meetings[day][idx:]
                startDay.insert(0, day+1)
        
    del meetings[day]
print(ans)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值