找出數組中重復的數字


 

題目一:在一個長度為n的數組里的所有數字都在0~n-1的范圍內。數組中某些數字是重復的,但是不知道有幾個數字重復了,也不知道每個數字重復了幾次。請找出數組中任意一個重復的數字。例如,如果輸入長度為7,的數組{2,3,1,0,2,5,3},那么對應的輸出是重復的數組2或者3。(n個元素,n種可能的取值)

解法一:先對數組進行排序,然后再查找排序后的數組中的重復元素

def selectedSort(lis):
for i in range(0, len(lis)):
        minVal = lis[i]
        minInd = i
        #找出最小的元素
        for j in range(i+1,len(lis)):
            if minVal>=lis[j]:
                minVal=lis[j]
                minInd=j
        #交換
        lis[minInd]=lis[i]
        lis[i]=minVal
    return lis
lis=[8,5,3,3,7,6,3,9,1,8]
lis_order=selectedSort(lis)
print(lis)

 

解法二:開辟一個新數組B,每次掃描源數組A中的元素,如果不在B中,就加入B中,如果在B中,就找到一個重復的元素

lisA=[8,5,3,3,7,6,3,9,1,8]
def findDuplicates(lisA):
    lisB = []
    for i in lisA:
        if i in lisB:
            print("找到一個重復的元素:%d"%i)
            break
        else:                   #當前掃描的元素不在lisB中,就加入到lisB中
            lisB.append(i)
            continue
findDuplicates(lisA)

 

解法三:因為列表總共有n個元素,所有元素可能取到的元素有0~n-1,共n種。如果不存在重復的數字,那么排序后數字i將會出現在下標為i的位置。現在讓我們重新掃描數組,

  • 當掃描到下標為i的數字時,首先比較這個數字(記為m)與i是否相等:
    • 如果是,繼續掃描下一個元素,
    • 如果不是,則再拿它與第m個數字比較:
      • 如果它和第m個數字相同,就找到了一個重復的元素;
      • 如果不同,就將m與第m個數字互換。接下來繼續重頭開始,重復換這個比較。

 

lisA=[8,0,2,3,7,6,4,2,1,5]
def findDuplicates(lisA):

    i=0
    while i <len(lisA) and lisA!=[]:
        m = lisA[i]
        if m == i:    
            i += 1
        else:
            if m == lisA[m]:
                print('找到一個重復的元素:%d' % m)
                break
            else:
                temp = lisA[i]
                lisA[i] = lisA[m]
                lisA[m] = temp
                i = 0

findDuplicates(lisA)

 


 

題目二:

在一個長度為n+1的數組里的所有數字都在1~n范圍內,所以數字中至少有一個數字是重復的。請找出數組中任意一個重復的數字,但是不能修改數組。例如,如果輸入長度為8的數組{2,3,5,4,3,2,6,7},那么對應的輸出是重復的數字2或3。(n+1個元素,n種可能的取值)

解法一:同上題解法二,開辟一個大小為n+1的新數組

解法二:避免使用O(n)的輔助空間。我們把取值空間[1,n]從中間的數字m分為兩部分,前面一部分為1~m,后面一部分為m+1~n。如果數組中元素落在前面一部分的元素個數多於m個,那么數組中重復的元素一定落在前半區間;否則,數組中重復的元素一定落在后半區間。然后,我們可以繼續將包含重復元素的區間一分為二,直到找到一個重復的元素。

lisA=[8,1,2,3,7,6,7,4,9,5,10]

def findDuplicates(lisA):
    """找到重復元素,返回True;否則,返回False"""
    low=1
    high=len(lisA)-1

    while low<=high:
        mid=(low+high)//2

        #統計數組中落在前半部分區間中的元素的個數
        count_low=0
        for i in lisA:
            if i in range(low,mid+1):
                count_low+=1

        #判斷落在長度為1的區間中的數組元素個數
        if high==low:
            if count_low>1:                 #如果大於1,則找到重復的元素
                return low
            else:
                break

        #比較前半部分區間長度與落在該區間內元素的個數,決定將前半部分/后半部分區間繼續一分為二
        if count_low>(mid-low+1):
            high=mid
        else:
            low=mid+1

    return False

print(findDuplicates(lisA))

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM