找到第二次出现时索引最小的第一个重复数字

问题描述 投票:0回答:10

这是一个关于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:
python algorithm python-2.7 dictionary data-structures
10个回答
15
投票

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   

2
投票

我认为你可以尝试在这里使用索引技术。由于您提到数字在 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)


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]}

现在,在这个提示之后,您需要研究索引值中需要哪些操作才能获得您想要的输出,我会让您解决这个问题,毕竟这是一个练习。如果有任何步骤描述得不好,请告诉我。


0
投票

正如我在另一篇文章中标红的那样,关键是使用字典。这是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    

0
投票
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 给出超出时间限制的错误。


0
投票

为了更快获得结果,我们需要使用集合而不是列表。

def first_duplicate(arr):
        uniques = set()
        for item in arr:
            if item in uniques:
                return item
            else:
                uniques.add(item)
    
        return -1

0
投票

这是一个快速的解决方案

  1. 创建一个集合

  2. 循环数组

  3. 检查集合中是否存在某个项目,然后返回,否则将其添加到集合中

  4. 如果没有重复项,则返回-1

    func 解决方案(a: [Int]) -> Int { var mySet = 设置() 对于 a{ 中的 num 如果 mySet.contains(num){ 返回数字 } 别的{ mySet.insert(num) } } 返回-1 }


0
投票

我测试了下一个 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 []

0
投票

我使用递归来做到这一点,而不是使用我使用的列表,它更优化,与使用循环相同的复杂性,但这样做是为了好玩: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]

-2
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.