百度松果班——python算法题

文章介绍了6个Python编程中的算法题目,包括游乐园中碰碰车的运动模拟、数组的三合一操作、数据流中位数的实时计算、硬币塔的问题、寻找最大平均值的子数组以及括号序列的合法子串。这些题目涵盖了动态规划、数据结构和逻辑推理等多个方面。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.游乐园

题目

游乐园玩碰碰车,其中有一种碰碰车是在一条直线上行驶。该碰碰车有一个初始朝向和初始位置,并且以每秒一个单位的速度向初始方向前行,当它和其它碰碰车相遇时,它们会立刻掉头(由于速度很快,掉头时间可以忽略)。你可以算出它们在t秒后的位置吗?

格式:

输入格式:
	第一行有两个数字n(1-1000),t(0-1000),分别表示:碰碰车的数量和所用时间:
	接下来n行,每一行都有两个数字:x,f分别表示第n辆碰碰车的位置和方向
	(0<x≤105,-1表示向左,1表示向右)。
输出格式:
	输出行,每一行两个数字,分别表示碰碰车最后的位置和方向
	(-1表示向左,1表示向右,0表示两车相遇)。

示例:

输入:5 2
	 4 1
	 5 -1
	 7 1
	 2 1
	 6 -1
	 
输出:4 0
	 4 0
	 9 1
	 3 -1
	 6 1

结果

class CAR ():
    def __init__(self,x=None,f=None,ID=None):
        self.x = x
        self.f = f
        self.ID = ID

n,t = map(int,input().split())
car = [CAR() for i in range(n)]
for i in range(n):
    car[i].x,car[i].f = map(int,input().split())
    car[i].ID = i+1

# 不用建立id列表的话直接用carTemp[i].ID赋值的话,会错误(不知道为啥)
id = []
carTemp=sorted(car,key= lambda car:car.x)
for i in range(n):
    id.append(carTemp[i].ID)

for i in range(n):
    car[i].x=car[i].x+car[i].f*t
car.sort(key=lambda car:car.x)

for i in range(n):
    car[i].ID = id[i]

    if i>0 and car[i].x==car[i-1].x or i<n-1 and car[i].x==car[i+1].x:
        car[i].f = 0 
car.sort(key=lambda car:car.ID)

for i in range(n):
    print(car[i].x,car[i].f)

2.三合一

题目

有一个数组,每一个位置有一个1-9的数,现对其进行三合一操作

三合一操作有若干轮:每一轮,从前往后扫,如果三个相邻的数的和小于等于“轮次*3”,则这三个数合并为一个数。如果能合,本轮的下一次扫描就从三个数后面的第一个数开始扫;如果不能合,就从这三个数的第二个数开始扫。他们相加的和经过有限轮后,该数组肯定会变为一个数或两个数。

现在需要你求出一共进行了多少轮(没有进行任何操作的轮次也算)。

格式

输入格式:第一行一个整数n
		第二行n个整数
输出格式:一行一个整数,表示进行了多少轮

示例

输入:3
	 1 2 3
输出:2

代码

使用链表

class ListNode():
    def __init__(self,val,next=None):
        self.val=val
        self.next=next

class LinkList():
    def __init__(self):
        self.head = None
    def initList(self,data):
        self.head = ListNode(data[0])
        cur = self.head
        pre = self.head
        for i in data[1:]:
            node = ListNode(i)
            pre.next = node
            pre = pre.next
        return cur

n = int(input())
data = list(map(int,input().split()))
linkList = LinkList()
linkList = linkList.initList(data)
cnt = 0
while linkList.next and linkList.next.next:
    cur = linkList
    while cur and cur.next and cur.next.next:
        cnt += 1
        sum = cur.val + cur.next.val + cur.next.next.val
        if sum <= cnt*3:
            cur.val = sum
            cur.next = cur.next.next.next
            cur = cur.next
        else:
            cur = cur.next

print(cnt)

暴力,使用两个list

n = int(input())
a = list(map(int,input().split()))
cnt = 0
while len(a) > 2:
    b = [] # 每次循环都清空b列表
    le = len(a)
    i = 0
    while i < le:
        if i + 2 < le:
            s1 = a[i] + a[i+1] + a[i+2]
            if s1 <= (cnt+1)*3:
                b.append(s1)
                i += 3
            else:
                b.append(a[i])
                i += 1
        else:
            b.append(a[i])
            i += 1
    a = b # 循环结束后,重置a列表
    cnt += 1

print(cnt)

3.数据流中位数

题目

对于数据流问题,小码哥需要设计一个在线系统,这个系统不断的接受一些数据,并维护这些数据的一些信息。
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
请帮小码哥设计一个支持以下两种操作的系统:
+num --> 从数据流中添加一个整数k到系统中(0<k<232).
?–> 返回目前所有元素的中位数。

格式

输入格式:第一行输入一个整型n(n≤100000)
		第二行输入n个操作
输出格式:?询问时输出中位数,每个操作一行,保证每次查询都合法

示例:

输入:
5
+ 1
+ 2
?
+ 3
?
输出:
1.5
2

代码

使用heapq模块建立小根堆,堆头为堆的最小值。如果将内部元素全取负,则成为大根堆,堆头为最大。每次循环,更新大根堆和小根堆,奇数时中位数在大根堆max_heap中。

import heapq

max_heap = []
min_heap = []
n = int(input())
for _ in range(n):
    x = input()
    if x.startswith('+'):
        num = int(x[-1])
        # 如果两个堆都为空,或者num小于等于最大堆的根节点(即列表左半部分的最大值),则将num加入最大堆
        if not max_heap or num <= -max_heap[0]:
            heapq.heappush(max_heap, -num)
        else:
            # 否则将num加入最小堆
            heapq.heappush(min_heap, num)
        # 调整两个堆的大小,使其相差不超过1,并且最大堆不小于最小堆
        if len(max_heap) > len(min_heap) + 1:
            heapq.heappush(min_heap, -heapq.heappop(max_heap))
        elif len(min_heap) > len(max_heap):
            heapq.heappush(max_heap, -heapq.heappop(min_heap))

    else:
        # 如果两个堆大小相等,则中位数是两个根节点的平均值
        if len(max_heap) == len(min_heap):
            mid = (-max_heap[0] + min_heap[0]) / 2
            if mid == int(mid): # mid是浮点数,如果是2.0这样的需要转成整数2 
                mid = int(mid)
        else:
            # 否则中位数是较大的那个堆的根节点
            mid = -max_heap[0]
        print(mid)

4.硬币塔

说实话没看懂题目啥意思()

题目

一个k级的硬币塔从下到上,由1个银币,一个k-1级硬币塔,k个金币,一个k-1级硬币塔,1个银币堆成。其中,0级硬币塔只有一个金币。
问:n级硬币塔从下向上数i个有几个金币。
格式

输入格式:一行用空格隔开的两个整数几,i
输出格式:一个整数表示答案

示例

输入:513
输出:6

代码

代码也没看懂。。。

# 计算每一层的硬币个数
def tower(k):
    if k == 0:
        return 1
    return 2+k+2*tower(k-1)
# 计算每一层的金币个数
def count(k):
    if k == 0:
        return 1
    return k+2*count(k-1)

def todo(k,i,res):
    if k == 0:
        if i>0:
            res[0] += 1
            return 
    else:
        num = tower(k)
        temp = tower(k-1)
        if i <= k:
            res[0] += 0 # ???这是啥操作
        elif i >= num - k:
            res[0] += count(k)
        elif i > temp + k + 1:
            res[0] += count(k-1) + k
            todo(k-1,i-temp-k-1,res)
        elif i > temp + 1:
            res[0] += count(k-1) + i - temp -1
        elif i > k:
            todo(k-1,i-1,res)

n,i = map(int,input().split())
if i <=n:
    print(0)
else:
    res = [0]
    todo(n,i,res)
    print(res[0])

5.最大平均值

题目

给一个数组,长度为n,找一个长度大于等于m的子区间,使这个区间的元素的平均值最大。

格式

输入格式:第一行输入整数n和m,数据间用空格隔开;
		接下来n行,每行输入一个整数a:.
输出格式:输出一个整数,表示平均值的最大值乘以1000再向下取整之后得到
的结果。

示例

输入:
10 6
6 
4
2
10
3
8
5
9
4
1
输出:
6500

代码

a = []
amax = 0
amin = 1e7

def check_mid(mid,n,m):
    sum = [0 for _ in range(n + 1)]
    for i in range(1,n + 1):
        sum[i] = sum[i-1] +a[i-1]-mid
    for i in range(m,n+1):
        minn = 0
        minn = min(minn,sum[i-m])
        if sum[i] > minn:
            return True
    else:
        return False

# 将输入存在列表中
n, m = map(int,input().split())
amax = 0
amin = 1e7
for _ in range(n):
    val = float(input())
    a.append(val)
    if val > amax:
        amax = val
    if val < amin:
        amin = val

while amax > amin + 10e-7:
    mid = (amax + amin) / 2.0
    if check_mid(mid,n,m):
        amin = mid
    else:
        amax = mid

print(int(1000*amax))

6.括号家族

题目

小码哥在研究只有左括号和右括号组成的序列。给出一个括号序列,求出最长合法子
串和它的数量(合法的定义:这个序列中左右括号匹配)。
例如:(()合法,)()( 也不合法,但()()(())合法。

格式

输入格式:输入一行只有左括号和右括号组成的序列(只包含小括号)。
输出格式:输出两个数字:最长子字符串的长度,以及此类子字符串的数量,如
果没有这样的子字符串,则输出 0 1

示例

输入:()()))()()(()
输出:4 2

代码

s = input()
def solution(s):
    stack = [] # 存放括号的索引
    ans = 0 # 记录最长合法子串长度
    cnt = 0 # 记录个数
    stack.append(-1)
    for i in range(len(s)):
        if s[i] == '(': # 最开始必须是(,)在最前面无意义
            stack.append(i)

        else:
            stack.pop()
            if not stack:
                stack.append(i)
            else:
                cur_len = i - stack[-1]
                if cur_len > ans: # 长度大于最大长度,重置ans和cnt
                    ans = cur_len
                    cnt = 1
                elif cur_len == ans: # 等于最大长度,cnt++
                    cnt += 1
    return (ans, cnt)
ans,cnt = solution(s)
if ans == 0:
    print('0 1')
else:
    print(f'{ans} {cnt}')

杂七杂八(小知识点)

  1. 一次性建立多个类
    采用列表car = [CAR() for i in range(n)] 而不是car = [CAR()]*3
  2. input()格式转换
    input() 函数接受一个标准输入数据,返回为 string 类型。
    将其转换为int型可以直接n = int(input())
    但如果使用input().split()的话,返回值为列表,不能直接int(列表)转为int格式,应该使用map函数n,t = map(int,input().split())
  3. sort 和sorted
    sort直接修改原列表,无返回值;sorted返回新列表,修改原列表不影响新列表。
# 使用sorted()函数对列表进行排序,返回一个新的列表
sorted_lst = sorted(lst, key=lambda obj: obj.f)

# 使用list.sort()方法对列表进行排序,修改原始列表
lst.sort(key=lambda obj: obj.f)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值