Python刷题记录(21-30)
题目来源PTA平台
PAT (Basic Level) Practice (中文)
@TOC
1021 个位数统计
给定一个 k 位整数 N=d**k−110k−1+⋯+d1101+d0 (0≤d**i≤9, i=0,⋯,k−1, d**k−1>0),请编写程序统计每种不同的个位数字出现的次数。例如:给定 N=100311,则有 2 个 0,3 个 1,和 1 个 3。
输入格式:
每个输入包含 1 个测试用例,即一个不超过 1000 位的正整数 N。
输出格式:
对 N 中每一种不同的个位数字,以 D:M
的格式在一行中输出该位数字 D
及其在 N 中出现的次数 M
。要求按 D
的升序输出。
输入样例:
100311
输出样例:
0:2
1:3
3:1
思路:
利用set集合进行去重,最后遍历得出个数并输出
代码:
n = list(input())
a = set(n)
b = sorted(list(a))
for i in b:
num = 0
for j in n:
if j == i:
num += 1
print(i+':'+str(num))
1022 D进制的A+B
输入两个非负 10 进制整数 A 和 B (≤230−1),输出 A+B 的 D (1<D≤10)进制数。
输入格式:
输入在一行中依次给出 3 个整数 A、B 和 D。
输出格式:
输出 A+B 的 D 进制数。
输入样例:
123 456 8
输出样例:
1103
思路:
10进制内的转换,常规思路,要注意的是a+b=0时也要有输出
代码:
def translate(a, b, c):
l = []
ans = a+b
if ans == 0:
return ['0']
while ans != 0:
t = ans % c
l.append(str(t))
ans = ans//c
l.reverse()
return l
n = [int(x) for x in input().split()]
print(''.join(translate(n[0], n[1], n[2])))
1023 组个最小数
给定数字 0-9 各若干个。你可以以任意顺序排列这些数字,但必须全部使用。目标是使得最后得到的数尽可能小(注意 0 不能做首位)。例如:给定两个 0,两个 1,三个 5,一个 8,我们得到的最小的数就是 10015558。
现给定数字,请编写程序输出能够组成的最小的数。
输入格式:
输入在一行中给出 10 个非负整数,顺序表示我们拥有数字 0、数字 1、……数字 9 的个数。整数间用一个空格分隔。10 个数字的总个数不超过 50,且至少拥有 1 个非 0 的数字。
输出格式:
在一行中输出能够组成的最小的数。
输入样例:
2 2 0 0 0 3 0 0 1 0
输出样例:
10015558
思路:
输入存储后,如果0的个数不为零先输出后面第一个不为0的然后再按需输出剩下的
代码:
a = [int(x) for x in input().split()]
if a[0] != 0:
for i, j in enumerate(a):
if j != 0 and i != 0:
print(i, end='')
a[i] -= 1
break
for i, j in enumerate(a):
if j != 0:
print(str(i)*j, end='')
print()
1024 科学计数法
科学计数法是科学家用来表示很大或很小的数字的一种方便的方法,其满足正则表达式 [±][1-9].
[0-9]+E[±][0-9]+,即数字的整数部分只有 1 位,小数部分至少有 1 位,该数字及其指数部分的正负号即使对正数也必定明确给出。
现以科学计数法的格式给出实数 A,请编写程序按普通数字表示法输出 A,并保证所有有效位都被保留。
输入格式:
每个输入包含 1 个测试用例,即一个以科学计数法表示的实数 A。该数字的存储长度不超过 9999 字节,且其指数的绝对值不超过 9999。
输出格式:
对每个测试用例,在一行中按普通数字表示法输出 A,并保证所有有效位都被保留,包括末尾的 0。
输入样例 1:
+1.23400E-03
输出样例 1:
0.00123400
输入样例 2:
-1.2E+10
输出样例 2:
-12000000000
思路:
以字符串的形式输入,按E分成前后两部分,t保存前部的数字,n表示E的幂
如果时负数先输出一个’-’
如果n<0,表明小数点往前挪,先输出’0.‘再输出(-n)-1个0和t即可
如果n>0,表面小数点往后挪,如果n<len(t)-1先输出t的前n+1个数字,在输出’.'和t剩下部分,否则输出t然后补上n-len(t)+1个0
代码:
a, b = input().split('E')
if a[0] == '-':
print('-', end='')
t = ''.join(a[1:].split('.'))
n = int(b)
if n < 0:
print('0.'+'0'*(-n-1)+t)
else:
if n < len(t)-1:
for i in range(n+1):
print(t[i], end='')
print('.'+t[n+1:])
else:
print(t+'0'*(n-len(t)+1))
1025 反转链表
给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转。例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4;如果 K 为 4,则输出应该为 4→3→2→1→5→6,即最后不到 K 个元素不反转。
输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤105)、以及正整数 K (≤N),即要求反转的子链结点的个数。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。
接下来有 N 行,每行格式为:
Address Data Next
其中 Address
是结点地址,Data
是该结点保存的整数数据,Next
是下一结点的地址。
输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218
输出样例:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
思路:
刚做没有多大思路,参考柳婼大佬的做法后豁然开朗
使用列表将节点的值和next地址存入,下标为改节点地址
然后新开一个列表存入链表,便利进行调换最后输出
部分反向的代码可以参考这个
list[i:i+m] = reversed(list[i:i+m])
最后使用sys库中的输入方式,解决测试点5的超时问题,但是使用sys中的输出方式仍然会超时,希望有大佬能解答下
代码:
import sys
strat, n, m = map(int, input().split())
data = [0 for i in range(100005)]
next = [0 for j in range(100005)]
list = [0 for zi in range(100005)]
for i in range(n):
a, b, c, = map(int, sys.stdin.readline().split())
data[a] = b
next[a] = c
sum = 0
while strat != -1:
list[sum] = strat
sum += 1
strat = next[strat]
for i in range(0, sum-sum % m, m):
list[i:i+m] = reversed(list[i:i+m])
for i in range(sum-1):
print('%05d %d %05d' % (list[i], data[list[i]], list[i+1]))
print('%05d %d -1' % (list[sum - 1], data[list[sum - 1]]))
1026 程序运行时间
要获得一个 C 语言程序的运行时间,常用的方法是调用头文件 time.h,其中提供了 clock() 函数,可以捕捉从程序开始运行到 clock() 被调用时所耗费的时间。这个时间单位是 clock tick,即“时钟打点”。同时还有一个常数 CLK_TCK,给出了机器时钟每秒所走的时钟打点数。于是为了获得一个函数 f 的运行时间,我们只要在调用 f 之前先调用 clock(),获得一个时钟打点数 C1;在 f 执行完成后再调用 clock(),获得另一个时钟打点数 C2;两次获得的时钟打点数之差 (C2-C1) 就是 f 运行所消耗的时钟打点数,再除以常数 CLK_TCK,就得到了以秒为单位的运行时间。
这里不妨简单假设常数 CLK_TCK 为 100。现给定被测函数前后两次获得的时钟打点数,请你给出被测函数运行的时间。
输入格式:
输入在一行中顺序给出 2 个整数 C1 和 C2。注意两次获得的时钟打点数肯定不相同,即 C1 < C2,并且取值在 [0,107]。
输出格式:
在一行中输出被测函数运行的时间。运行时间必须按照 hh:mm:ss
(即2位的 时:分:秒
)格式输出;不足 1 秒的时间四舍五入到秒。
输入样例:
123 4577973
输出样例:
12:42:59
思路:
因为要四舍五入先+50再去除以100即可,得到
n=(b-a+50)//100
后面按照正常思路转换为小时分钟和秒即可
代码:
a, b = map(int, input().split())
s = (b-a+50)//100
t = s % 60
h = s // 3600
m = s // 60 - h*60
print('%02d:%02d:%02d' % (h, m, t))
1027 打印沙漏
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
思路:
先计算每个沙漏所需的符号个数
然后按沙漏形状打印并打印剩下的符号数
代码:
a = 1
b = []
for i in range(3, 60, 2):
b.append(a)
a += i*2
n, f = map(str, input().split())
n = int(n)
for i in range(30):
if n < b[i]:
break
ans = n-b[i-1]
for j in range(i, 0, -1):
print((f*(j*2-1)).center(i*2-1).rstrip())
for j in range(1, i):
print((f*(j*2+1)).center(i*2-1).rstrip())
print(ans)
1028 人口普查
某城镇进行人口普查,得到了全体居民的生日。现请你写个程序,找出镇上最年长和最年轻的人。
这里确保每个输入的日期都是合法的,但不一定是合理的——假设已知镇上没有超过 200 岁的老人,而今天是 2014 年 9 月 6 日,所以超过 200 岁的生日和未出生的生日都是不合理的,应该被过滤掉。
输入格式:
输入在第一行给出正整数 N,取值在(0,105];随后 N 行,每行给出 1 个人的姓名(由不超过 5 个英文字母组成的字符串)、以及按 yyyy/mm/dd
(即年/月/日)格式给出的生日。题目保证最年长和最年轻的人没有并列。
输出格式:
在一行中顺序输出有效生日的个数、最年长人和最年轻人的姓名,其间以空格分隔。
输入样例:
5
John 2001/05/12
Tom 1814/09/06
Ann 2121/01/30
James 1814/09/05
Steve 1967/11/20
输出样例:
3 Tom John
思路:
设置max,min,f表示人数,当时间又比max小或者比min大的时候更新
时间比较可以通过字符串比较实现
注意人数为0的时候只输出0
测试点4通过sys库的输入解决
代码:
import sys
n = int(input())
min = ['', '1814/09/06']
max = ['', '2014/09/06']
f = 0
for i in range(n):
name, time = map(str, sys.stdin.readline().split())
if time < '1814/09/06' or time > '2014/09/06':
continue
f += 1
if time < max[1]:
max = [name, time]
if time > min[1]:
min = [name, time]
if f == 0:
print('0')
else:
print(f, max[0], min[0])
1029 旧键盘
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现。现在给出应该输入的一段文字、以及实际被输入的文字,请你列出肯定坏掉的那些键。
输入格式:
输入在 2 行中分别给出应该输入的文字、以及实际被输入的文字。每段文字是不超过 80 个字符的串,由字母 A-Z(包括大、小写)、数字 0-9、以及下划线 _
(代表空格)组成。题目保证 2 个字符串均非空。
输出格式:
按照发现顺序,在一行中输出坏掉的键。其中英文字母只输出大写,每个坏键只输出一次。题目保证至少有 1 个坏键。
输入样例:
7_This_is_a_test
_hs_s_a_es
输出样例:
7TI
思路:
输入并将全部字符转换为大写,创建ans记录坏掉的键
遍历str1,在ans和str2找不到的记录
遍历str2,在ans和str1找不到的记录
输出ans
代码:
str1 = input().upper()
str2 = input().upper()
ans = ''
for i in str1:
if str2.find(i) == -1 and ans.find(i) == -1:
if i.isdigit():
ans += i
else:
ans += i.upper()
for i in str2:
if str1.find(i) == -1 and ans.find(i) == -1:
if i.isdigit():
ans += i
else:
ans += i.upper()
print(ans)
1030 完美数列
给定一个正整数数列,和正整数 p,设这个数列中的最大值是 M,最小值是 m,如果 M≤m**p,则称这个数列是完美数列。
现在给定参数 p 和一些正整数,请你从中选择尽可能多的数构成一个完美数列。
输入格式:
输入第一行给出两个正整数 N 和 p,其中 N(≤105)是输入的正整数的个数,p(≤109)是给定的参数。第二行给出 N 个正整数,每个数不超过 109。
输出格式:
在一行中输出最多可以选择多少个数可以用它们组成一个完美数列。
输入样例:
10 8
2 3 20 4 5 1 6 7 8 9
输出样例:
8
思路:
当初简单的以为使用双层循环查找就行,结构测试点4超时
后来参考了柳婼大佬的思路也不行,最后参考了网上大佬的想法解决
柳婼大佬的解决方式在得到最优解时还可能会进行查找,导致超时
大致思路如下:用m记录使用最多的数,从头遍历列表,内循环从i+m开始,如果满足条件m+1,直到不满足退出内循环开始下次外循环,最后找到最大m
代码:
import sys
n, p = map(int, input().split())
l = [int(x) for x in sys.stdin.readline().split()]
l.sort()
m = 0
for i in range(n):
min_p = l[i]*p
end = i+m
if end >= n:
break
for j in range(end, n):
if l[j] <= min_p:
m += 1
else:
break
print(m)