这是一个关于codefights的问题:
给定一个数组 a,其中仅包含从 1 到 a.length,找到第一个重复的数字,第二个数字的重复数字 出现次数具有最小索引。换句话说,如果有更多 超过 1 个重复数字,返回第二个数字 出现的索引比其他出现的第二次出现的索引小 数字确实如此。
我一直在努力弄清楚如何在 python 中完成这个任务。我不确定我是否走在正确的道路上,如果是的话,在从 d 字典中找到特定值后,我似乎无法弄清楚如何访问我的索引字典。我想获取 d 字典中所有大于 1 的值,然后从索引中获取这些值,然后索引中较小的值就是答案。
如果我的想法完全错误,请告诉我。
def firstDuplicate(a):
d = {}
index = {}
for i in a:
if i in d:
d[i] += 1
else:
d[i] = 1
for i,e in enumerate(a):
if e in d:
index[e] = i
else:
index[e] = i
for key,val in d.items():
if val > 1:
Emm...简单的方法有什么问题吗?
def firstDuplicate(a):
aset = set()
for i in a:
if i in aset:
return i
else:
aset.add(i)
print(firstDuplicate([7,4,5,6,4,6,3]))
词典版本:
adict = {}
for i in a:
if i in adict:
return i
else:
adict[i] = 1
我认为你可以尝试在这里使用索引技术。由于您提到数字在 1 到 a.length 范围内,因此您可以从列表中检索该元素,转到索引
l[i]
并将该元素更改为 -l[l[i]]
即
l[l[i]] = -1 * l[l[i]]
执行此操作时,如果遇到负值,则返回该索引处存在的元素的绝对值。如果您在执行此操作时遇到问题,请告诉我。这是代码:(忘记之前提到了):
l = [7,4,5,6,4,2,3]
found = 0
for i in range (0 , 6):
item = abs(l[i])
if(l[item - 1] > 0):
l[item - 1] = -1 * l[item - 1]
else:
found = abs(l[i])
break
print (found)
output : 4
时间复杂度:O(n)
空间:O(1)
您的第二个
for
循环对 if
和 else
条件执行相同的操作,让我们更改该 for
循环,而且,无需存储出现次数少于两次的元素,因此我们将该条件添加为出色地。这里的第二个循环的作用是,使用列表理解,它存储列表中元素的所有出现(著名解决方案),然后我们将其存储在我们的indexdic
中。最后,打印两个词典看看它们是什么样子的:
def firstDuplicate(a):
d = {}
indexdic = {}
for element in a:
if a.count(element) > 1:
if element in d:
d[element] += 1
else:
d[element] = 1
for key in d:
indexdic[key] = [i for i, x in enumerate(a) if x == key]
print('d: ', d)
print('indexdic: ', indexdic)
运行这个:
>>> firstDuplicate(['a','b','c','a','d','d','b'])
d: {'a': 2, 'd': 2, 'b': 2}
indexdic: {'a': [0, 3], 'd': [4, 5], 'b': [1, 6]}
现在,在这个提示之后,您需要研究索引值中需要哪些操作才能获得您想要的输出,我会让您解决这个问题,毕竟这是一个练习。如果有任何步骤描述得不好,请告诉我。
正如我在另一篇文章中标红的那样,关键是使用字典。这是Python 3的解决方案。索引是数字,因此你会知道你以前是否见过它。
def firstDuplicate(a):
oldies={}
notfound=True
for i in range(len(a)):
try:
if oldies[a[i]]==a[i]:
notfound=False
return a[i]
except:
oldies[a[i]]=a[i]
if notfound:
return -1
def firstDuplicate(a):
lst = list()
x=-1
for i in a:
if i in lst:
x = i
break
else:
lst.append(i)
return(x)
这个答案解决了 20/22 输入。 Codefights 给出超出时间限制的错误。
为了更快获得结果,我们需要使用集合而不是列表。
def first_duplicate(arr):
uniques = set()
for item in arr:
if item in uniques:
return item
else:
uniques.add(item)
return -1
这是一个快速的解决方案
创建一个集合
循环数组
检查集合中是否存在某个项目,然后返回,否则将其添加到集合中
如果没有重复项,则返回-1
func 解决方案(a: [Int]) -> Int { var mySet = 设置() 对于 a{ 中的 num 如果 mySet.contains(num){ 返回数字 } 别的{ mySet.insert(num) } } 返回-1 }
我测试了下一个 Haskell 解决方案,但对于一个非常大的列表(长度 >= 100000),它仍然需要 4 秒以上
firstRepeated :: [Int] -> [Int] -> Int
firstRepeated [] [] = -1
firstRepeated [] _ = -1
firstRepeated (x:xs) ys
| any (x==) ys = x
| otherwise = firstRepeated xs (x:ys)
对于呼叫,只需发送输入和空列表:
firstRepeated a []
我使用递归来做到这一点,而不是使用我使用的列表,它更优化,与使用循环相同的复杂性,但这样做是为了好玩:D:
dupFree = set()
def solution(a,i=0):
if i == len(a):
return -1
if a[i] not in dupFree:
dupFree.add(a[i])
return solution(a,i+1)
return a[i]
Javascript解决方案
function solution(a) {
return a.filter((n, i) => a.indexOf(n) !== i)[0] || -1;
}
console.log(solution([2, 1, 3, 5, 3, 2])); // 3
console.log(solution([2, 2])); // 2
console.log(solution([2, 4, 3, 5, 1])); // -1