1. 程式人生 > >陣列-BAT面試經典試題:絕對眾數,零子陣列,最大子陣列和

陣列-BAT面試經典試題:絕對眾數,零子陣列,最大子陣列和

1.絕對眾數問題

定義:給定N個數,稱出現次數最多的數為眾數:若某眾數出現的次數大於N/2,稱該眾數為絕對眾數。

如:A={1,2,1,3,2}中,1和2都是眾數,但都不是絕對眾數;A={1,2,1,3,1}中,1是絕對眾數。

已知給定的N個整數存在絕對眾數,以最低的時空負責度計算該絕對眾數。

演算法分析:

刪除陣列A中的兩個不同的數,絕對眾數不變:若兩個數有一個是絕對眾數,則剩餘的N-2個數中,絕對眾數仍大於(N-2)/2;若兩個數中沒有絕對眾數,則不影響絕對眾數

演算法描述:

記m為候選絕對眾數,出現的次數為c,初始化為0.

遍歷陣列A:

若C==0,則m=A[i];

若c\neq0且m\neqA[i],則同時刪掉m和A[i];

若c\neq0且m==A[i],則c++;

python實現:

def Mode(arr):
    count=0
    m=arr[0]
    for i in range(len(arr)):
        if count==0:
            m=arr[i]
            count=1
        elif m!=arr[i]:
            count-=1
        else:
            count+=1
    return m

if __name__ =='__main__':
    arr=[8,8,6,1,6,8,1,1,1,1,1]
    print(Mode(arr))

2.零子陣列

求對於長度為N的陣列A,求連續子陣列的和最接近0的值,及對應的子陣列。如陣列A=[1,-2,3,10,-4,7,2,-5].

演算法思路:

1)計算前 i 個元素的和,新的陣列記為sum;

2) 對陣列sum排序;

3)計算排序後sum陣列相鄰兩個元素的差,差最接近零的即為本題所求1。

如果要求返回對應的子陣列:記差最接近為0的兩個元素值分別為 m 和 n,找到 m 和 n 第1)步中sum陣列對應的索引位置,i  和 j ,i 和 j 之間的元素即為所求子陣列。

python實現:

def MinSubarray(A):
    sum_1=[]
    for i in range(len(A)+1):
        sum_1.append(sum(A[:i]))
    sum_=sorted(sum_1)
    difference=abs(sum_[1]-sum_[0])
    m,n=sum_[1],sum_[0]
    result=difference
    for i in range(len(sum_)-1):
        difference=abs(sum_[i+1]-sum_[i])
        if result>difference:
            result=difference
            m,n=sum_[i+1],sum_[i]
    idx_1=sum_1.index(m)
    idx_2=sum_1[idx_1+1:].index(n)+idx_1+1
    subarr=A[idx_1:idx_2]
    return result,subarr


if __name__ =='__main__':
    A=[1,-2,3,10,-4,7,2,-5]
    value,subarr=MinSubarray(A)
    print(value)
    print(subarr)

3. 最大子陣列

給定一個數組A[0,1,...n-1],求A的連續子陣列,使得該子陣列的和最大。例如陣列A=[1,-2,3,10,-4,7,2,-5].

演算法分析:

第一種方法,返回最大子陣列和的值:

記S[i]為以A[i]結尾的陣列中和最大的子陣列,則S[i+1]=max(S[i]+A[i+1],A[i+1]),S[0]=A[0],遍歷 i 。動態規劃:最優子問題,時間複雜度O(n)。

第二種方法,返回最大子陣列和的值和子陣列。

計算以A[i]結尾的元素的和,記錄A[i]前面和最小的位置與當前 i 之間的子陣列。從1到N遍歷,即可得所求。

def MaxSubarray(A):
    sum1=A[0]
    result=sum1
    subarr=[]
    subarr.append(A[0])
    for i in range(1,len(A)):
        if sum1>0:
            sum1+=A[i]
            subarr.append(A[i])
        else:
            sum1=A[i]
        result=max(sum1,result)
    return result
def MaxSubarray1(A):
    begin=end=0
    Sum=A[0]
    result=Sum
    for i in range(1,len(A)):
        if Sum>0:
            Sum+=A[i]
        else:
            Sum=A[i]
            fromNew=i
        if result<Sum:
            result=Sum
            begin=fromNew
            end=i
    return result,A[begin:end]

if __name__ =='__main__':
    A=[1,-2,3,10,-4,7,2,-5]
    print('First method:')
    print(MaxSubarray(A))
    value,arr=MaxSubarray1(A)
    print('Second Method:')
    print(value)
    print(arr)

未完待續……

說明:本部落格的題目和演算法思路來自小象學院BAT演算法特訓班網路課