PAT乙级python编程练习(五)

PAT乙级python编程练习(五)

  • PAT乙级python编程练习(五)
    • 1021 个位数统计
    • 1022 D进制的A+B
    • 1023 组个最小数
    • 1024 科学计数法
    • 1025 反转链表

1021 个位数统计

给定一个 k 位整数 N=dk110k1++d1101+d0(0di9,i=0,,k1,dk1>0) N = d ​ k − 1 10 ​ k − 1 ​ + ⋯ + d 1 10 1 ​ + d 0 ( 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

思路及注意点

  1. 此题用字典很方便。以字符串形式输入,对于每个字符,若字典中存在这个键,则该键对应的值+1;若不存在这个键,则添加该键入字典,并使其值初始化为1.
  2. 最后d.items()获取字典中的每一项,并根据每项的键来排序。

代码

s = input()
d = {}
for x in s:
    if x not in d:
        d[x] = 1
    else:
        d[x] += 1
result = sorted(d.items(), key=lambda x: x[0])
for item in result:
    print('%s:%d' % (item[0], item[1]))

运行结果

测试点 结果 耗时 内存
0 答案正确 23 ms 3056KB
1 答案正确 24 ms 3056KB
2 答案正确 24 ms 3076KB

1022 D进制的A+B

输入两个非负 10 进制整数 A 和 B (≤2^30−1),输出 A+B 的 D (1 < D ≤ 10)进制数。

输入格式:
输入在一行中依次给出 3 个整数 A、B 和 D。

输出格式:
输出 A+B 的 D 进制数。

输入样例:

123 456 8

输出样例:

1103

思路及注意点

  1. 利用进制转换的“除基取余”法:除以D,得到商Q1和余数R1,商Q1继续除以D,得到商Q2和余数R2,依次循环,直到商为0。将得到的一系列余数反转输出即该数对应的D进制数。

代码

s = list(map(int, input().split()))
c = s[0] + s[1]
if c == 0:
    print(0)
else:
    if s[2] == 10:
        print(c)
    else:
        r = []
        while c:
            r.append(c % s[2])
            c = c // s[2]
        r.reverse()
        for _ in r:
            print(_, end='')

运行结果

测试点 结果 耗时 内存
0 答案正确 23 ms 3056KB
1 答案正确 23 ms 3076KB
2 答案正确 23 ms 3076KB
3 答案正确 23 ms 3076KB
4 答案正确 24 ms 3056KB
5 答案正确 23 ms 3076KB

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

思路及注意点

  1. 首先根据输入的每个数字出现的次数,得到备用数字的列表。然后将这个列表排序,若列表的第一个数为0,则往右取一直到找到非零数为止,输出这个非零数,将这个非零数从列表中“弹出”,接下来按照顺序输出列表中的数;若列表中的第一个数不为0,直接按照顺序输出即可。

代码

s = list(map(int, input().split()))
num = []
for i, x in enumerate(s):
    num.extend([i]*x)
num.sort()
result = []
for i in range(len(num)):
    if num[i]:
        print(num.pop(i), end='')
        break
for x in num:
    print(x, end='')

运行结果

测试点 结果 耗时 内存
0 答案正确 30 ms 3080KB
1 答案正确 22 ms 3056KB
2 答案正确 23 ms 3312KB
3 答案正确 23 ms 3164KB
4 答案正确 22 ms 3056KB

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

思路及注意点

  1. 又用到正则表达式啦,参见前面博客中1003 我要通过!这题
  2. 利用正则表达式的分组(group),提取数字部分和对应的指数部分,分指数正负情况处理小数点。

代码

import re
s = input()
if s[0] == '-':
    print('-', end='')
m = re.match('[+-]([1-9]\\.[0-9]+)E([+-])([0-9]+)', s)
s1 = m.group(1)
s2 = int(m.group(3))
if s2 == 0:
    print(s1)
else:
    if m.group(2) == '+':
        if s2 < len(s1)-2:
            print(s1[0] + s1[2:2+s2] + '.' + s1[2+s2:])
        else:
            print(s1[0] + s1[2:] + '0' * (s2-len(s1)+2))
    else:
        print('0.' + '0' * (s2-1) + s1[0] + s1[2:])

运行结果

测试点 结果 耗时 内存
0 答案正确 35 ms 3844KB
1 答案正确 34 ms 3888KB
2 答案正确 35 ms 3960KB
3 答案正确 35 ms 3868KB
4 答案正确 34 ms 3896KB
5 答案正确 34 ms 3956KB
6 答案正确 34 ms 3992KB

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 (≤10^5 )、以及正整数 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

思路及注意点

  1. 以字典类型存储结点,结点地址为键,对应的值是一个元组,包含自身的地址、数据、下一个结点的地址。
  2. 下面方法是链表的常用做法,先根据前后地址关系串联链表,再对串联好的链表进行操作(本题就是每四个为一块反向输出)。
  3. 输出时要注意下一个结点的地址,在串联好的链表的每一块(四个为一块)内,后三个的下一个结点都输出成前一个结点的地址,而第一个结点在反向后需要考虑所接下一块是否为完整的一块,若下一块不到四个,则这个结点的next就是下一块的第一个结点的地址;若接下来仍有完整的一块,则这个结点的next为下一块最后一个结点的地址;若这已经是最后一块,接下来无结点,则next为-1.
  4. 注意输入中可能有不在链表内的无效结点。
  5. 又遇到输入量很大的情况了。。。所以这里又有一个测试点会运行超时。求大神帮助!

代码

begin, n, k = input().split()
n = int(n)
k = int(k)
d = {}
while n:
    node = input().split()
    d[node[0]] = node
    n -= 1
nodes = []
p = begin
while p != '-1':
    nodes.append(d[p])
    p = d[p][2]
num = len(nodes) // k
r = len(nodes) % k
for i in range(num):
    for j in range((i+1)*k-1,i*k,-1):
        print(nodes[j][0], nodes[j][1], nodes[j-1][0])
    if i < num - 1:
        print(nodes[i*k][0], nodes[i*k][1], nodes[(i+2)*k-1][0])
    else:
        if r == 0:
            print(nodes[i*k][0], nodes[i*k][1], -1)
        else:
            print(nodes[i*k][0], nodes[i*k][1], nodes[(i+1)*k][0])
            for l in range(r):
                print(nodes[num*k+l][0], nodes[num*k+l][1], nodes[num*k+l][2])

运行结果

测试点 结果 耗时 内存
0 答案正确 24 ms 3184KB
1 答案正确 24 ms 3204KB
2 答案正确 24 ms 3204KB
3 答案正确 23 ms 3164KB
4 答案正确 23 ms 3184KB
5 运行超时 0 ms 0KB
6 答案正确 25 ms 3184KB

你可能感兴趣的:(PAT乙级python编程练习(五))