【python学习笔记】几道笔试题(3)

继续记录最近做的一些笔试题。

第一题:

下列选项中,不可能是快速排序第二趟排序结果的是:

A、2,3,5,4,6,7,9 
B、2,7,5,6,4,3,9 
C、3,2,5,4,7,6,9
D、4,2,3,5,7,6,9

尝试:快排的思想是找到一个值(一般选择数组第一个元素),将比这个值小的所有元素放到该值左边,比这个值大的元素放到该值右边,然后分别对左右使用快排并合并,直到切分后的数组长度为1为止。因此我判断数组内排序的大致顺序是:最小,较小,较大,最大。B中7、3位置与这种顺序不符。

def fast_sort(arr):
    if len(arr) <= 1:
        return arr
    else:
        middle_value = arr[0]
        left = []
        middle = [middle_value]
        right = []
        for i in arr[1:]:
            if i<middle_value:
                left.append(i)
            elif i>middle_value:
                right.append(i)
            else:
                middle.append(i)
        left = fast_sort(left)
        right = fast_sort(right)
        return left+middle+right

修改:当快排中间值正好是待排数组中最小值(或最大值)时,快排退化为冒泡排序,因此经过这一轮排序,仅被选中的值会被排序正确。这种情况就会造成元素分布不会呈低-中-高这样的顺序,而是正确-乱序(或乱序-正确)。快排第n趟排序结果校验中给出的解法是:每趟排序就会至少有一个元素排在了最终的位置上,因此只需要比较排序后与正确结果的相同位数。

分析:快排利用中间值,将比中间值小(大)的元素排在左(右)边,因此经过这次排序后,中间值的位置一定正确。B的情况是被选为中间值是最小值和最大值,即只有首尾两个元素排序正确。

第二题:

输入包括多组测试数据。每组输入第一行是两个正整数N和M(0 < N <= 30000,0 < M < 5000),分别代表学生的数目和操作的数目。学生ID编号从1编到N。第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。接下来又M行,每一行有一个字符C(只取‘Q’或‘U’),和两个正整数A,B,当C为'Q'的时候, 表示这是一条询问操作,他询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。当C为‘U’的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。

对于每一次询问操作,在一行里面输出最高成绩。

样例输入:

扫描二维码关注公众号,回复: 1521206 查看本文章
5 7
1 2 3 4 5
Q 1 5
U 3 6
Q 3 4
Q 4 5
U 4 5
U 2 9
Q 1 5

样例输出:

5
6
5
9

尝试:

import sys
while True:
    n, m = list(map(int, sys.stdin.readline().strip().split()))
    init = list(map(int, sys.stdin.readline().strip().split()))
    for i in range(m):
        line = sys.stdin.readline().strip().split()
        if line[0] == 'Q':
            a, b = list(map(int, line[1:]))
            print(max(init[a-1:b]))
        elif line[0] == 'U':
            a, b = list(map(int, line[1:]))
            init[a-1] = b

报错,第三行没有足够变量解构赋值。应该是测试样例用完未退出,在外层加上try-except。之后测试用例中有一项“Q 9 5”没有跑通,加if判断ab大小。

修改:

import sys
try:
    while True:
        n, m = list(map(int, sys.stdin.readline().strip().split()))
        init = list(map(int, sys.stdin.readline().strip().split()))
        for i in range(m):
            line = sys.stdin.readline().strip().split()
            if line[0] == 'Q':
                a, b = list(map(int, line[1:]))
                if a>b:
                    a, b = b, a
                print(max(init[a-1:b]))
            elif line[0] == 'U':
                a, b = list(map(int, line[1:]))
                init[a-1] = b
except:
    pass

第三题:

开发一个简单错误记录功能小模块,能够记录出错的代码所在的文件名称和行号。 
1.记录最多8条错误记录,对相同的错误记录(即文件名称和行号完全匹配)只记录一条,错误计数增加;(文件所在的目录不同,文件名和行号相同也要合并)
2.超过16个字符的文件名称,只记录文件的最后有效16个字符;(如果文件名不同,而只是文件名的后16个字符和行号相同,也不要合并)

3.输入的文件可能带路径,记录文件名称不能带路径。

输入:

一行或多行字符串。每行包括带路径文件名称,行号,以空格隔开。

文件路径为windows格式如:E:\V1R2\product\fpgadrive.c 1325

输出:

将所有的记录统计并将结果输出,格式:文件名代码行数数目,一个空格隔开,如: fpgadrive.c 1325 1 

结果根据数目从多到少排序,数目相同的情况下,按照输入第一次出现顺序排序。

如果超过8条记录,则只输出前8条记录。如果文件名的长度超过16个字符,则只输出后16个字符

尝试:

import sys
if __name__ == '__main__':
    dic = {}
    try:
        while True:
            line = sys.stdin.readline().strip().split()
            if len(line) == 0:
                break
            pos = line[0].rfind('\\')
            line = line[0][pos+1:]+' '+line[1]
            if line in dic:
                dic[line] = dic[line]+1
            else:
                dic[line] = 1
        res_value = [0 for i in range(8)]
        res_key = [0 for i in range(8)]
        for i in dic:
            if dic[i]<=res_value[-1]:
                continue
            for j in range(8):
                if dic[i]>res_value[j]:
                    res_value.insert(j, dic[i])
                    res = i.split()[0][-16:]+' '+i.split()[1]+' '+str(dic[i])
                    res_key.insert(j, res)
                    break
        resPrint = ' '
        resPrint = resPrint.join(res_key[:8])
        print(resPrint)
    except:
        pass

思路:读取完整文件名称(输出时再截取16位)和行号,作为key,值为出现次数,存入字典中。读取完毕后,遍历字典,res_value中存放前8位最大值。当字典中的值大于列表中j位置的值时,将字典的value插入res_value中,key插入res_key中。当有相同大小的value时,从前向后遍历且判断是否大于可将后放入的key存在后面,满足题意。提交,未能AC。

问题分析:

1、python中字典类型是无序的,不会记录放入顺序。当遍历字典时,不会以添加的先后顺序遍历,而是以key字典序遍历,因此需改用列表记录顺序。

2、当输入文件数较小时,res_key中还存在初始填充的0值,因此需要判断前8位中是否还有0元素。

3、输出格式不符合规范。经过测试,本题需要每个错误项作为一行,而不是拼接为一个字符串。

修改:

import sys
if __name__ == '__main__':
    dic = []
    dic_value = []
    while True:
            line = sys.stdin.readline().strip().split()
            if len(line) == 0:
                break
            pos = line[0].rfind('\\')
            line = line[0][pos+1:]+' '+line[1]
            if line in dic:
                dic_value[dic.index(line)] = dic_value[dic.index(line)]+1
            else:
                dic.append(line)
                dic_value.append(1)
    res_value = [0 for i in range(8)]
    res_key = [0 for i in range(8)]
    for i in range(len(dic)):
        if dic_value[i]<=res_value[-1]:
            continue
        for j in range(8):
            if dic_value[i]>res_value[j]:
                res_value.insert(j, dic_value[i])
                res = dic[i].split()[0][-16:]+' '+dic[i].split()[1]+' '+str(dic_value[i])
                res_key.insert(j, res)
                break
    if res_key.index(0)<8:
        res_key_index = res_key.index(0)
    else:
        res_key_index = 8
    for i in range(res_key_index):
        print(res_key[i])

第四题:

现在有两堆石子,小今与小条玩游戏,2个人都足够聪明,两个人规定:每次每人只能从其中一堆中取走1个或2个或3个石子,最后将石子全部取完的人胜利.现在两堆石子的个数为8和9,请问如何安排才能让小今必胜?

思路:回溯法。为使小今赢得比赛,最后一种情况是小今取完还剩4块石头,小条无论怎么取下一步小今都会赢。因此需将石头控制在4的倍数,即小今第一步走取9块石头中的一个,之后只要控制石头数是4的倍数即可。

第五题:

所有新闻真实率到达了98%,工作人员在检验一个真实的新闻把它检验为一个虚假的新闻的概率为2%,而一个虚假的新闻被检验为真实的新闻的概率为5%.那么,一个被检验为真实的新闻确实是真实的新闻的概率是多大?

思路:被检验为真实的新闻包括两部分:真实新闻被检验为真实,虚假新闻被检验为真实。其中第一部分占比0.98*0.98约为0.96,第二部分占比0.02*0.95约为0.001,即被检测为真实的确实为真实新闻的概率为0.96/0.961约为0.99896。

猜你喜欢

转载自blog.csdn.net/orangecsy/article/details/79733377
今日推荐