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