题目
题目链接
描述
给定一个正整数数组(元素的值都大于零),输出数组中第二个重复出现的正整数,如果没有,则输出字符串"NOT EXIST"。
输入
第一行为整数m,表示有m组数据。
其后每组数据分两行:
第一行为正整数n(3 < n < 500),表示数组的长度;
第二行是n个正整数,正整数间用空格分开。
输出
有m行输出,每行输出对于数组中第二个重复出现的正整数,如果没有,则输出字符串"NOT EXIST"。
Code
-法1(错误示范)
m=int(input())
lis=[]
lis1=[]
for i in range(m):
n=int(input())
row= list(input().split())
for i in range(n):
if x not in lis:
lis.append(x)
lis1[i]=1
if x in lis:
index=index(x)
lis1[index]+=1
count=0
for x in range(len(lis)):
if lis1[x]>1:
count+=1
while count==2:
print(lis[x])
break
if count==0:
print("NOT EXIST")
错误分析
首先这是一段不完整的代码,缺少了求索引的代码
代码修正
m=int(input())
for i in range(m):
dic = dict()
n=int(input())
row=list(input().split())
for x in row:
if x not in dic:
dic[x]=1
else:
dic[x]+=1
lis1=list(dic.keys())
lis2=list(dic.values())
count=[]
for j in range(len(lis2)):
if lis2[j]>=2:
count.append(j)
if len(count)>=2:
print(int(lis1[count[1]]))
else:
print("NOT EXIST")
代码解析
- 修正的代码虽然可以完成所预期的功能,但是在创建完字典之后,没有很好的利用好这个字典,绕了一步。
- 是先把字典的键和值作为两个列表,通过下标遍历值列表,如果值>=2,把下标放进count列表
- 然后再根据count的长度判断有没有符合条件的,如果有就通过找第二个值,把它作为索引对应到键列表获取最终的数字。
代码再优化
m=int(input())
for i in range(m):
dic = dict()
n=int(input())
#这里可以不用转换成列表row=list(input().split())
for x in input().split():#因为split后返回的就已经是列表了
if x not in dic:
dic[x]=1
else:
dic[x]+=1
#在成功创建每个数字对应出现次数的字典之后,我们可以对原来的代码进行优化
count=[]
#类似于我用value作为评价指标,对key进行记录
for key,value in dic.items():#使用items可以同时获取字典的键和值
if value >=2:##如果值大于等于2了,说明重复出现
count.append(key)#这时候就把它对应的数字添加到列表里
if len(count)>=2:
print(str(count[1]))
else:
print("NOT EXIST")
代码解析
优化的代码则是利用键是输出目标,值是筛选条件,通过值把满足条件的键放在count新列表里面,直接输出count的第二个元素。其实修正的代码和再优化的代码都开辟了一个新的列表,然后找它的第二个元素,但是优化的代码使用items不仅看起来思路更清晰,而且更简洁
解题思路
- 首先,我们看输入的格式和输出的对应关系,第一行告诉我们有几组两行的数据;
- 接着,我们发现一组数据对应一行输入,所以,我们可以用一个大循环,针对每一组数据输出结果,在下一组数据进入循环后重新来过。(这是一个非常重要的前提思路)
- 其次,我们要开始对这个问题设计解决方案,题目要求找第二个重复的数
(其实我觉得这里面是有bug的,因为根据程序来说,它是遍历完所有数字,按顺序记录每个新数的出现次数;而歧义就是我们还可以把题意理解为第二个重复出现的数是5,因为虽然5和7都重复出现了,但是7先比5重复出现完,第二个7在5的前面)- 抛开歧义以设计者想让我们设计的程序的角度,我们需要创建一个字典–键是所有出现的数(不重复的)+值是对应数出现的次数
- 最后,在创建完字典后,我们需要利用字典来找到第二个重复出现的数;
- 第一,看它的值如果>=2,就说明键重复了;
- 第二,因为要找的是第二个,所以我们只能通过增加1个新的列表空间进行存储所有重复出现的键;
- 第三,我们判断新列表的长度,符合后输出第二个元素即为我们的答案
奇技淫巧
- Q:多组数据同时分行输入,同时分行输出,该怎么设计?
–>我们可以使用一个大的for循环,处理完一组数据就print;下一组数据,所有的操作从头来过 - 怎么利用遍历创建记录元素出现次数的列表呢?
–>见代码,可以直接记住,因为很经典!!!
dic=dict()
names=[]#一堆数据
for name in names:
if name not in dic:
dic[name]=1
else:
dic[name]+=1
- 怎么同时获取字典的键和值?
–>
字典同时获取键和值的代码为:
for key,value in 字典名.items():
回忆一下,列表同时获取下标和索引的代码为:
for index,value in enumerate(列表名):