之前一直刷的剑指offer,听闻真题的坑挺多也不以为意,今天试刷了一道,踩出了许多经验。题目描述如下:

地址: https://www.nowcoder.com/test/question/3897c2bcc87943ed98d8e0b9e18c4666?pid=260145&tid=23740103

首先被输入输出整的一头雾水,后来得知即标准的输入(键盘)与输出(屏幕)。

于是开始动手编程。首先python里的标准输入:

Python input() 函数

Python3.x 中 input() 函数接受一个标准输入数据,返回为 string 类型。

Python2.x 中 input() 相等于 eval(raw_input(prompt)) ,用来获取控制台的输入。

raw_input() 将所有输入作为字符串看待,返回字符串类型。而 input() 在对待纯数字输入时具有自己的特性,它返回所输入的数字的类型( int, float )。

注意:input() 和 raw_input() 这两个函数均能接收 字符串 ,但 raw_input() 直接读取控制台的输入(任何类型的输入它都可以接收)。而对于 input() ,它希望能够读取一个合法的 python 表达式,即你输入字符串的时候必须使用引号将它括起来,否则它会引发一个 SyntaxError 。

除非对 input() 有特别需要,否则一般情况下我们都是推荐使用 raw_input() 来与用户交互。

注意:python3 里 input() 默认接收到的是 str 类型。

可以得知,以input()读取输入后,此时是以字符串的形式。

因此考虑以split函数处理。

Python3 split()方法


描述

split()通过指定分隔符对字符串进行切片,如果参数 num 有指定值,则仅分隔 num+1 个子字符串

语法

split()方法语法:

str.split(str="", num=string.count(str))

参数

  • str -- 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。
  • num -- 分割次数。默认为 -1, 即分隔所有。

返回值

返回分割后的字符串列表。

可以得知,分割对象必须是字符串,且返回的是列表。在本题中,尝试用空格作为分隔符(默认就是空格),在本地中运行示例,成功,但是提交之后不行,出现 IndexError: list index out of range

查找https://blog.csdn.net/zhoubbt/article/details/53673637 得知,

这个错误出现大约有两种情况: 
第1种可能情况 
list[index]index超出范围

第2种可能情况 
list是一个空的 没有一个元素 
进行list[0]就会出现该错误

因此应该是分割的时候出了问题,于是加入换行符,因为自带的split不支持多个分隔符,因此考虑用re模块,https://blog.csdn.net/zhuzuwei/article/details/78886662 得知:

因此改写成 (' |\n',s),但是依然不行,后来发现原来这里的分行的意思就是一组数据输入完毕。因此要改写程序。 

 s = s + ' ' +input() 
S = s.split(' ')  尤其注意,s要加空格连接,因为每行末尾没用空格。

之后在本地运行,成功输出,在牛客网的调试页面中也成功通过,但是遇到了一个难题,如图:

也就是,显示只通过了百分之十的样例,第二个例子显示输出为空,请检查一下你的代码有没有循环输入处理多个case。顺着连接点过去,https://www.nowcoder.com/discuss/276。知道了原来是循环输入的,也就是依次输入好多数据!!!

举个栗子:https://www.nowcoder.com/questionTerminal/dae9959d6df7466d9a1f6d70d6a11417 求两个数的和的时候,写成这样才可以处理一直输入的情况:

while True:
    try:
        s = input()
        S = s.split()
        a = int(S[0])
        b = int(S[1])
        print(a+b)
    except:
        break

这个例子非常重要!!!是处理OJ问题的基础!

之后把程序改写成了这种形式,再debug之后,顺利通过测试!不得不说测试用例找的真是好,无死角测试出来了我的Bug...

完整程序如下,没用进行优化有些杂乱,但是确实是可以通过的!具体看注释吧!

while True: #注意此格式
    try:
        s = input() #开始读取第一行
        S = s.split(' ')  #将第一行分割
        M = int(S[0])    #如果不加int,M与N都是str,并不是数字
        N = int(S[1])
        numid = M     #ID的长度
        fre = N       #操作的次数
        nummake = 0   #第几次操作的计数
        ID = [0]*numid #初始化ID列表
        s = s + ' ' +input()  #开始读取开始的ID,注意要加空格,因为上一行最末没有空格
        S = s.split(' ')   #分割
        row2 = S[2:2+numid] # 得出第二行,其实直接读不加起来也可以
        for i in range(len(row2)): # 初始化,一定要注意,这里的ID里面的元素仍然是str。str可以 
                                    #比较大小,但是规则不一样!
            ID[i] = row2[i]       #注意i是从0开始的
        ID = list(map(int,ID))  #很重要!将ID中的str转换为int
        while fre > 0:           #当还有操作次数时候进行循环
            #print('while')
            s = s + ' ' +input() 
            S = s.split(' ') 
            rows = S[2+numid+nummake:2+numid+nummake+3]  #操作行,每行必有三个元素
            #print(rows)
            fre = fre-1  #可用次数减少
            nummake = nummake+3 #操作往后移动3,其实直接读取也行。。
            A = int(rows[1]) #要转换成int
            B = int(rows[2])
            if rows[0] == 'Q': #判断相等
                #print('Q')
                if A-1 <B:      #要分A-1(开闭区间的问题)与B的大小讨论,否则会有些情况错误
                    #print(ID[A-1:B])
                    print(int(max(ID[A-1:B])))
                elif A-1 == B:
                    print(ID[B])
                else:
                    print(int(max(ID[B-1:A])))
            elif rows[0] =='U':
        #print('U')
                ID[A-1] = B   #都是int
    except:    #标准格式
        break

总结:

1 在本地调试时候,注意按停止,否则会一直执行循环

2 列表与字符串相互转换是常见问题

3 引用官网:作者:管理员
链接:https://www.nowcoder.com/discuss/276
来源:牛客网 2.2 对于传统ACM的OJ模式题目,你的程序需要stdin(标准输入)读取输入,然后stdout(标准输出)来打印结果,举个例子,你可以使用c语言的scanf或者c++的cin来读取输入,然后使用c语言的printf或者c++的cout来输出结果。代码禁止读取和写入任何文件,否则判题系统将会返回运行错误。OJ一次处理多个case,所以代码需要循环处理,一般通过while循环来出来多个case。

https://www.cnblogs.com/Mufasa/p/10221403.html本地的简洁代码

5 搞懂输入跟输出十分重要,是做笔试题目的基础