题目
题目描述
给定一个长度为 NN 的数组 A=[A1,A2,⋅⋅⋅,AN],数组中有可能有重复出现的整数。
现在小明要按以下方法将其修改为没有重复整数的数组。小明会依次修改A2,A3,⋅⋅⋅,AN。
当修改 Ai 时,小明会检查 Ai 是否在 A1 ∼ Ai−1 中出现过。如果出现过,则小明会给 AiAi 加上 1 ;如果新的 Ai仍在之前出现过,小明会持续给 Ai加 1 ,直 到 Ai没有在 A1A1 ∼ Ai−1Ai−1 中出现过。
当 AN 也经过上述修改之后,显然 A 数组中就没有重复的整数了。
现在给定初始的 A 数组,请你计算出最终的 A 数组。
输入描述
第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,⋅⋅⋅,AN。
其中,1≤N≤105,1≤Ai≤1061≤N≤105,1≤Ai≤106。
输出描述
输出 N 个整数,依次是最终的 A1,A2,⋅⋅⋅,AN。
输入输出样例
示例
输入
5
2 1 1 3 4
输出
2 1 3 4 5
题解
循环
按照常规方法,通过30%:
import os
import sys
def list_find(x,y,z):
for i in range(y,z):
if a[i] == x:
return i
return -1
n = int(input())
a = [ int(i) for i in input().split()]
for i in range(1,n):
while list_find(a[i],0,i)!=-1:
a[i]+=1
for i in range(n):
print(a[i],end=" ")
set
对于上述代码进行优化,采用set集合,通过40%:
n = int(input())
a = [ int(i) for i in input().split()]
s = set()
for i in range(n):
while a[i] in s:
a[i]+=1
s.add(a[i])
print(a[i],end=" ")
hash
采用hash优化,仍通过40%:
v = [0]*1000005
n = int(input())
a = [ int(i) for i in input().split()]
for i in a:
while v[i] != 0:
i += 1
v[i]=1
print(i,end=" ")
并查集
采用并查集时,通过率为100%
def find_set(x,s):
if x != s[x]:
s[x] = find_set(s[x],s)
return s[x]
N = 1000002
A = [0]*N
s = list(range(N))
n = int(input())
A = [0] + [ int(i) for i in input().split()]
for i in range(1, n+1):
root = find_set(A[i],s)
A[i] = root
s[root] = find_set(root+1, s)
print(* A[1:])
附录
在 Python 中,print(*A[1:]) 这行代码涉及到两个重要的操作:切片操作和拆包操作,下面为你详细解释。
代码构成分析
1. 切片操作 A[1:]
切片操作是 Python 中用于从序列(如列表、元组、字符串等)中提取部分元素的一种操作。A[1:] 表示从序列 A 中提取从索引为 1 的元素开始到序列末尾的所有元素,形成一个新的序列。索引从 0 开始计数,所以索引为 1 的元素是序列 A 中的第二个元素。
例如,若 A = [10, 20, 30, 40, 50],那么 A[1:] 的结果就是 [20, 30, 40, 50]。
2. 拆包操作 *
在 Python 中,* 符号用于序列(如列表、元组等)的拆包操作。当在函数调用中使用 * 符号时,它会将序列中的元素解包,作为独立的参数传递给函数。
在 print(*A[1:]) 中,* 会把A[1:] 这个序列中的元素拆分开,然后将这些元素作为独立的参数传递给 print() 函数。