四道简单的笔试题
Q1:分橘子问题
问题描述
班级里有n名同学从前到后排成一排,且已经得知了这些同学的成绩,其中第i名同学的成绩是ai。班主任想根据同学们上个阶段的绩来评定发橙子的数量。为了激励成绩优秀同学,发橙子时需要满足如下要求;
- 相邻同学中成绩好的同学的橙子必须更多。若相邻的同学成绩一样,则它们分到的数量必须平等。
- 每个同学至少分配一个橙子
由于预算有限,班主任希望在符合要求的情况下发出尽可能少的橙子。,至少需要准备多少橙子呢?
输入格式
第一行是一个整数n,表示学生数量。 接下来一行有n个整数,第i个整数a,表示第i个同学的成绩,
输出格式
输出答案,也就是需要最少准备多少个橙子。
输入输出样例
输入 5 3 4 5 4 3 输出 9
样例1解释
每位同学拿到的橙子的数量分别是1,2,3,2.1,所以至少需要准备9个
数据规模与约定
保证1<n≤10^6,0<ai<10。
思路
初始数组list
list | 3 | 4 | 5 | 4 | 3 |
---|---|---|---|---|---|
nums | 1 | 1 | 1 | 1 | 1 |
第一步先进行填充
list | 20 | 3 | 4 | 5 | 4 | 3 | 20 |
---|---|---|---|---|---|---|---|
nums | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
while循环,==当比左边的同学分数高,并且橙子没有比左边同学多,或者比右边同学高,但橙子没有比右边同学多==的情况,给他分一个橙子,继续循环
第一轮:
list | 20 | 3 | 4 | 5 | 4 | 3 | 20 |
---|---|---|---|---|---|---|---|
nums | 1 | 1 | ==2== | 1 | 1 | 1 | 1 |
第二轮:
list | 20 | 3 | 4 | 5 | 4 | 3 | 20 |
---|---|---|---|---|---|---|---|
nums | 1 | 1 | 2 | ==2== | 1 | 1 | 1 |
第三轮:
list | 20 | 3 | 4 | 5 | 4 | 3 | 20 |
---|---|---|---|---|---|---|---|
nums | 1 | 1 | 2 | ==3== | 1 | 1 | 1 |
第四轮:
list | 20 | 3 | 4 | 5 | 4 | 3 | 20 |
---|---|---|---|---|---|---|---|
nums | 1 | 1 | 2 | 3 | ==2== | 1 | 1 |
遍历结束,返回sum(list)-2
代码
n = int(input())
l = list(map(int,input().split()))
l.insert(0,20)
l.insert(n+1,20)
nums = [1 for _ in range(n+2)]
index = 1
while index <= n:
if (l[index] > l[index-1] and nums[index]<=nums[index-1]) or (l[index]>l[index+1]and nums[index]<=nums[index+1]):
nums[index] += 1
index = 1
index += 1
print(sum(nums)-2)
分析
时间复杂度O(n²),空间复杂度O(n)
Q2:从第几天开始不会再有树死亡?
问题描述
在一个花园中有一些树,每棵树都经过了杀虫处理,分别被喷洒了不同数量的杀虫剂。
当每天结束时,如果某棵树的杀虫剂含量比它左边的树的高,那么它会死去。 你会被告知每棵树的杀虫剂的初始含量。计算在第几天之后不再会有植物死去。
例子
p=[3,6,2,7,5] 在第一天和第二天,第1和第3颗树死亡,剩下的树为p = [3,2,5]。在第2天,第3颗树也死亡,剩下的树为p=[3,2]。
现在没有树比它左边的树的杀虫剂含量高了,所以结果为第2天。
输入
一个整型一维数组: N int p[n]
输出
从第几天开始不会再有树死亡
思路
list | 3 | 6 | 2 | 7 | 5 |
---|
第一步:填充左侧max(list)+1
list | 8 | 3 | 6 | 2 | 7 | 5 |
---|
第二步:遍历列表,寻找大于左侧的树,注意要更新list的长度
第一轮
list | 8 | 3 | 2 | 5 |
---|
第二轮
list | 8 | 3 | 2 |
---|
第三轮
由于此时并没有树被杀死,退出循环,day = 2
代码
l = list(map(int,input().split()))
# 填充
l.insert(0,max(l)+1)
l.insert(len(l),max(l)+1)
day = 1
while True:
index = 1
n = len(l)-2
sign = False
while index <= n:
if l[index]>l[index-1]:
sign = True
l.pop(index)
n = len(l)-2
index += 1
if not sign:
break
day += 1
print(day-1)
Q3:链表区间翻转
问题描述
将一个节点数为size链表m位置到n位置之间的区间反转,要求时间复杂度O(n)
例如:
给出的链表为1→2→3→4→5→NULL,m=2,n=4返回1→4→3→2→5→NULL.
数据范围:链表长度0<size<1000,O<mnssize,链表中每个节点的值满足|val |<1000要求:时间复杂度O(n)
示例1
输入: {1,2,3,4,5},2,4
输出: {1,4,3,2,5}
示例2
输入: {5},1,1
输出: {5}
思路
做的时候感觉编链表麻烦了点,取巧做了个列表翻转。
代码
s = input()
s = s.replace("{","")
s = s.replace("}","")
l = s.split(",")
start = int(l[len(l)-2])-1
end = int(l[len(l)-1])-1
for i in range(start, (start + end - 1) // 2 + 1):
tmp = l[i]
l[i] = l[start + end - i]
l[start + end - i] = tmp
print("{",end='')
print(l[0],end='')
for ss in l[1:len(l)-2]:
print(",",end='')
print(ss,end='')
print("}")
Q4:版本比较
问题描述
问题比较简单,就是两个版本号比较大小。
输入:
"1.0.1","1.0.11"
输出:
-1
输入:
"1.0.012","1.0.12"
输出:
0
输入:
"2.1.0","1.12.1"
输出:
1
思路
对输入进行转化后变成一个int的list,记下来逐一比较即可
代码
def fun(l1,l2):
min_len = min(len(l1),len(l2))
for i in range(min_len):
if int(l1[i]) > int(l2[i]):
return 1
elif int(l1[i]) < int(l2[i]):
return -1
if len(l1) > len(l2):
return 1
elif len(l1) < len(l2):
return -1
else:
return 0
s1,s2 = input().split(",")
s1 = s1[1:-1]
s2 = s2[1:-1]
l1 = s1.split(".")
l2 = s2.split(".")
print(fun(l1,l2))