之前一直刷的剑指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。
4 https://www.cnblogs.com/Mufasa/p/10221403.html本地的简洁代码
5 搞懂输入跟输出十分重要,是做笔试题目的基础