關於數組的一些面試題目及答案


 

 

1.給你一個數組,求一個k值,使得前k個數的方差 + 后面n-k個數的方差最小 ,時間復雜度可以到O(n)。

根據方差公式D(X)=E(x^2)-[E(X)]^2

def minVariance(arr):
    sum=0
    square_sum=0
    length=len(arr)
    left_var=[0]*length
    right_var=[0]*length
  #從左到右求每一段的方差
for i in range(length): sum+=arr[i] square_sum+=arr[i]*arr[i] left_var[i]=square_sum/(i+1)-(sum/(i+1))**2

sum = 0 square_sum = 0
#從右到左求每一段的方差
for j in range(length-1,-1,-1): sum+=arr[j] square_sum += arr[j] * arr[j] right_var[j] = square_sum / (length-j) - (sum / (length-j)) ** 2
  #二者合並,找出方差最小的兩斷 index
=0 variance=left_var[0]+right_var[0] for k in range(length-1): if left_var[k]+right_var[k+1]<variance: variance=left_var[k]+right_var[k] index=k+1 return index

 

2.給你一個只由0和1組成的字符串,找一個最長的子串,要求這個子串里面0和1的數目相等。     時間復雜度可以到O(n) 

這樣一種巧妙的解法:定義一個數據B[N], B[i]表示從A[0...i]中 num_of_0 - num_of_1,0的個數與1的個數的差。 那么如果arr[i] ~ arr[j]是符合條件的子串,一定有 B[i] == B[j],因為中間的部分0、1個數相等,相減等於0。 只需要掃一遍A[N]就能把B[N]構造出來了。

def findMaxEqualSequence(arr):
    count=[0,0]
    B=[0]*len(arr)
    dict_num={}
    curlen=0
    maxlen=0
    for i in range(len(arr)):
        count[arr[i]]+=1
     #數組B保存到當前i下標這一段中0出現的次數與1出現的次數之差 B[i]=count[0]-count[1]
     #如果到當前下標差值等於0,說明從開始到現在兩者出現次數是一樣的,當前下標+1就是滿足要求最長子串的長度,直接continue下一個就行了
if B[i]==0: maxlen=i+1
       continue
     #將差值第一次出現都保存在字典里面,以后每次計算一個差值都訪問一下字典,如果字典中有,說明字典保存的下標到當前下標這一段,出現0與1
#的個數是相等的,然后計算兩者下標之差,與maxlen做比較即可。 if dict_num.__contains__(B[i]): curlen=i-dict_num[B[i]] if curlen>maxlen: maxlen=curlen
#字典中沒有說明該差值第一次出現,就記錄在字典中
else: dict_num[B[i]]=i return maxlen

 3.給你一個數組,求一個數組的最大值和次大值

def getMaxAndNextMax(arr):
    max_val=arr[0]
    next_val=arr[0]
    for k in arr:
        if k>max_val:
            next_val=max_val
            max_val=k
        elif k>next_val:
            next_val=k

    return(max_val,next_val)
        
    
a=[-2.5,4,300,3,1000,8,100]
print(getMaxAndNextMax(a))

 4.給定一個n個整型元素的數組a,其中有一個元素出現次數超過n / 2,求這個元素。據說是百度的一道題

方法一:對數組進行排序,因為一個元素已經超過了一半,則中間位置的元素就必為該元素。

方法二:火拼方法。

來看這樣一個例子:

5 1 5 4 1 1 3 1 2 1 1

一共11個數字,其中1一共出現了6次。那么如何快速的找到這個6呢?我們來考慮這樣一個現實生活中的例子:有一群人在打群架,他們每個人有一個編號,代表自己所處的勢力,現在這一群人按照順序依次往廣場中央走,如果廣場內現在有和自己不是一個勢力的人,那么他就和其中一個同歸於盡,問,最后哪一個勢力的人會獲勝?我們按照這個意思,再來看一下剛才這個例子:

1)勢力5的一個人走進廣場中央,現在廣場中央有一個人,勢力是5

2)勢力1的一個人走進廣場中央,他發現廣場中央有一個勢力是5的人,於是同歸於盡,現在廣場上沒有人

3)勢力5的一個人走進廣場中央,現在廣場中央有一個人,勢力是5

4)勢力4的一個人走進廣場中央,他發現廣場中央有一個勢力是5的人,於是同歸於盡,現在廣場上沒有人

5)勢力1的一個人走進廣場中央,現在廣場有一個人,勢力是1

6)勢力1的一個人走進廣場中央,現在廣場有兩個人,勢力是2

……

可以發現,每一次火拼,勢力最大(也就是出現次數最多的那個數字)的那個每次最多只會死亡一個。而火拼最多會進行N/2次,出現頻率最高的那個數字最多只會損失N/2個,而題上告訴我們出現次數已經超過了一半,因此廣場上剩下的那個團伙的編號必然是出現次數做多的那個!這樣一來,代碼就非常好寫了。

def getAppearMoreThanHalf(arr):
    curVal=arr[0]
    count=1
    for i in range(1,len(arr)):
        if count==0:
            curVal=arr[i]
            count=1
            continue
        if arr[i]==curVal:
            count+=1
        else:
            count-=1 
    return curVal        
    
a=[3,5,7,7,7]
print(getAppearMoreThanHalf(a))

5.求數組中元素的最短距離

題目:給定一個含有n個元素的數組,找出數組中的兩個元素X和Y使得abs(x-y)最小

解題思路:先排序,然后遍歷元素。

 

6.求兩個有序數組的共同元素

充分利用數組有序的性質,用兩個指針i和j分別指向a和b,比較a[i]和b[j],根據比較結果移動指針,則有如下三種情況

1. a[i] < b[j],則i增加1,繼續比較

2. a[i] == b[j],則i和j皆加1,繼續比較

3. a[i] < b[j],則j加1,繼續比較

重復以上過程直到i或j到達數組末尾。

 

小小總結一下,對於在數組中進行查找的問題,可以分如下兩種情況處理

1. 如果給定的數組有序,那么首先應該想到Binary Search,所需O(logn)

2. 如果給定的數組無序,那么首先應該想到對數組進行排序,很多排序算法都能在O(nlogn)時間內對數組進行排序,然后再使用二分搜索,總的時間復雜度仍是O(nlogn)。

如果能做到以上兩點,大多數關於數組的查找問題,都能迎刃而解。

 

7.求數組中滿足給定和的數對

題目:給定兩個有序整型數組a和b,各有n個元素,求兩個數組中滿足給定和的數對,即對a中元素i和b中元素j,滿足i + j = d(d已知)

解析:兩個指針i和j分別指向數組的首尾,然后從兩端同時向中間遍歷。

// 找出滿足給定和的數對
void FixedSum(int* a, int* b, int n, int d)
{
    for (int i = 0, j = n - 1; i < n && j >= 0)
    {
        if (a[i] + b[j] < d)
            ++i ;
        else if (a[i] + b[j] == d)
        {
            cout << a[i] << ", " << b[j] << endl ;
            ++i ;
            --j ;
        }
        else // a[i] + b[j] > d
            --j ;
    }
}

 

8.字符串逆序

題目:給定一個含有n個元素的字符數組a,將其原地逆序(不能額外開辟空間)。

def strReverse(s):
    left=0
    right=len(s)-1
    while left<right:
        s[left],s[right]=s[right],s[left]
        left+=1
        right-=1    
    return s    

s="abcde"
print(strReverse(s))

 

9.數組元素重排問題

給定含有n個元素的整型數組a,其中包括0元素和非0元素,對數組進行排序,要求:

1. 排序后所有0元素在前,所有非零元素在后,且非零元素排序前后相對位置不變

2. 不能使用額外存儲空間

例子如下

輸入 0, 3, 0, 2, 1, 0, 0

輸出 0, 0, 0, 0, 3, 2, 1

解析:從尾部開始設置兩個指針,last指針指向后面第一個出現0的位置,first指向last前面的第一個非0元素,如果first是非0,則將值賦給last,然后last++,first++;如果first指向0,則繼續前進first++。

def Arrange(arr):
    length=len(arr)
    first=length-1
    last=length-1
#last從后面找到第一個0元素位置 if arr[last]!=0: while last>=0 and arr[last]!=0: last-=1 if last<0: return first=last-1 #這個時候開始遍歷走 while first>=0: if arr[first]!=0: arr[first],arr[last]=arr[last],arr[first] first-=1 last-=1 else: first-=1 return arr a=[6,0,3,0,2,1,0,0] print(Arrange(a))

 

10.找出絕對值最小的元素

題目:給定一個有序整數序列(非遞減序),可能包含負數,找出其中絕對值最小的元素,比如給定序列 -5, -3, -1, 2, 8 則返回1。

解析

  • 如果給定的序列中所有的數都是正數,那么數組的第一個元素即是結果。
  • 如果給定的序列中所有的數都是負數,那么數組的最后一個元素即是結果。
  • 如果給定的序列中既有正數又有負數,那么絕對值得最小值一定出現在正數和負數的連接處

 

def findAbsoluteMinVal(arr):
    if arr[0]>0:
        return arr[0]
    if arr[len(arr)-1]<0:
        return arr[len(arr)-1]
    for i in range(1,len(arr)):
        if arr[i]>0:
            return arr[i] if abs(arr[i-1])>arr[i] else abs(arr[i-1])

 11.two sum(leetcode題目一)

     未排序數組,找出兩個元素值等於target值,並返回下標,小的下標在前面。

def twoSum(self, nums, target):
        if len(nums)<1:
            return
        dict={}
        for i in range(len(nums)):
            if target-nums[i] in dict:
                return (dict[target-nums[i]],i)
            else:
                dict[nums[i]]=i

 


免責聲明!

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



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