一、設置左上角的座標(lu1,lu2)和右下角的座標(rd1,rd2),4個變量。按照題目打印python
(第一次:lu1=0,lu2=0---rd1=3,rd2=3)ios
二、打印完一次,左上角座標(lu1+=1,lu2+=1),右下角的座標(rd1 -= 1,rd2 -= 1),直到左上角座標在右下角座標的右下方。算法
(第二次:lu1=1,lu2=1---rd1=2,rd2=2)數組
def printmatrix(lu1,lu2,rd1,rd2,res): if lu1 == rd1: for i in range(lu2,rd2+1): res.append(matrix[lu1][i]) elif lu2 == rd2: for i in range(lu1,rd1+1): res.append(matrix[i][lu2]) else: curl1 , curl2 = lu1 , lu2 while curl2 != rd2: res.append(matrix[lu1][curl2]) curl2 += 1 while curl1 != rd1: res.append(matrix[curl1][rd2]) curl1 += 1 while curl2 != lu2: res.append(matrix[rd1][curl2]) curl2 -= 1 while curl1 != lu1: res.append(matrix[curl1][lu2]) curl1 -= 1 def OrderPrint(matrix): lu1 , lu2 = 0 , 0 rd1 , rd2 = len(matrix)-1 , len(matrix[0])-1 res = [] while lu1 <= rd1 and lu2 <= rd2: printmatrix(lu1,lu2,rd1,rd2,res) lu1 += 1 lu2 += 1 rd1 -= 1 rd2 -= 1 matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] OrderPrint(matrix)
和上一題同樣app
一、設置左上角的座標(lu1,lu2)和右下角的座標(rd1,rd2),4個變量。旋轉着改變矩陣curl
二、打印完一次,左上角座標(lu1+=1,lu2+=1),右下角的座標(rd1 -= 1,rd2 -= 1),直到左上角座標在右下角座標的右下方。函數
def rotate(matrix,lu1,lu2,rd1,rd2): times = rd1 - lu1 temp = 0 for i in range(times): temp = matrix[lu1][lu2+i] matrix[lu1][lu2+i] = matrix[rd1-i][lu2] matrix[rd1-i][lu2] = matrix[rd1][rd2-i] matrix[rd1][rd2-i] = matrix[lu1+i][rd2] matrix[lu1+i][rd2] = temp def rorateEdge(matrix): if not matrix or len(matrix) == 0 or len(matrix[0]) == 0: return matrix lu1 , lu2 , rd1 , rd2 = 0 , 0 , len(matrix)-1 , len(matrix[0])-1 while lu1 <= rd1 and lu2 <= rd2: rotate(matrix,lu1,lu2,rd1,rd2) lu1 += 1 lu2 += 1 rd1 -= 1 rd2 -= 1 return matrix matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] rorateEdge(matrix)
def printZMatrix(matrix): if len(matrix) == 0 or len(matrix[0])==0: return matrix ld1 , ld2 = 0 , 0 ru1 , ru2 = 0 , 0 res = [] end1 , end2 = len(matrix)-1 , len(matrix[0])-1 sign = False while ru1 <= end1: printlr(matrix,ld1,ld2,ru1,ru2,res,sign) ru1 += 1 if ru2 == end2 else 0 ru2 += 1 if ru2 != end2 else 0 ld2 += 1 if ld1 == end1 else 0 ld1 += 1 if ld1 != end1 else 0 sign = ~sign return res def printlr(matrix,ld1,ld2,ru1,ru2,res,sign): # sign = True if ru2 % 2 == 0 else False if sign: while ru1 <= ld1: res.append(matrix[ru1][ru2]) ru1 += 1 ru2 -= 1 else: while ld1 >= ru1: res.append(matrix[ld1][ld2]) ld1 -= 1 ld2 += 1 matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]] printZMatrix(matrix)
要求:要求時間複雜度爲O(Nlogk)和O(N)ui
若是先排序再找到最小的K個數,時間複雜度爲O(NlogN)url
採用棧來存儲當前K個最小的值,棧中數值升序排序。spa
若棧的大小<K 且當前元素比棧頂元素大,則往棧中加元素。
不然,若當前元素比棧頂元素小,則將當前元素加入棧中,調整棧中元素的大小順序並保證棧的大小爲K。
def sortarr(arr,k): if not arr or k >= len(arr): return arr stack ,temp = [] , [] for i in range(len(arr)): if not stack: stack.append(arr[i]) else: if len(stack) < k and arr[i] >= stack[-1]: stack.append(arr[i]) while stack and arr[i] < stack[-1]: temp.append(stack.pop()) if temp: stack.append(arr[i]) stack.extend(temp[1:][::-1]) temp = [] return stack arr = [1,3,7,9,4,6,3,1,2,5,0] k = 4 sortarr(arr,k)
一直維護一個大小爲k的大根堆,這個堆表示目前選出的k個最小的數。
接下來遍歷整個數組,
遍歷過程當中看當前數是否比堆頂元素小,若是是的話,將堆頂元素替換成當前的數,而後從堆頂向下調整堆;
不然,不進行任何操做。遍歷結束後,堆中的k個數就是答案。
import heapq def KNumHeap(arr,k): if k <= 0 or k >= len(arr) or len(arr) == 0: return arr max_heap = [] for i in range(len(arr)): cur = -arr[i] if len(max_heap) < k: heapq.heappush(max_heap,cur) else:
#heappushpop函數能夠將一個cur元素插入最大堆中,保持堆的大小不變,即若cur > 堆頂元素,則cur不插入,堆不變。不然,刪除堆頂元素,cur插入堆中正確位置 heapq.heappushpop(max_heap,cur) return list(map(lambda x:-x,max_heap)) arr = [1, 9, 2, 4, 7, 6, 3] k = 3 KNumHeap(arr,k)
給定一個無序數組arr,求出須要排序的最短子數組長度。
例如:arr = 【1,5,3,4,2,6,7】返回4,由於只有【5,3,4,2】須要排序。
從右往左遍歷,找最小值,若是最小值左邊有比其大的數,索引就到此處。
從左往右遍歷, 找最大值,若是最大值右邊有比其小的數,索引就到此處。
如如下,紅圈2爲從右往左遍歷到的最小值,左邊比其大的數爲其左邊綠框的5,3,8,4。【爲什麼不是1,由於1,2已在最左邊放好】,nominindex = 2
紅圈9爲從左往右遍歷獲得的最大值,右邊比其小的數爲4。maxindex = 10
結果巍峨10-2+1=9
def getMinLen(arr): if not arr or len(arr) < 2: return 0 minnum = arr[len(arr)-1] nominindex = -1 for i in range(len(arr)-2,-1,-1): if arr[i] > minnum: nominindex = i else: minnum = min(minnum,arr[i]) if nominindex == -1: return 0 maxnum = arr[0] nomaxindex = -1 for i in range(1,len(arr)): if arr[i]<maxnum: nomaxindex = i else: maxnum = max(maxnum,arr[i]) return nomaxindex - nominindex + 1 arr = [1,2,5,3,8,4,2,6,7,9,4] getMinLen(arr)
【4,3,7,4,4,4,5】,設置一個cand和time變量。開始,
開始,cand = 4,time= 1,
遇到下一個數3,二者不一樣,time - 1 = 0
遇到下一個數7,由於time=0,因此cand重置爲=7,time=1
遇到下一個數4,cand和4不一樣,因此time - 1 =0
遇到下一個數4,time = 0,cand重置爲4,time= 1
遇到下一個數4,cand和4相同,time + 1 = 2
遇到下一個數5,cand和5不一樣,time - 1 = 1
故:剩下的數cand爲4。
而後從頭開始遍歷,判斷4是否出現超過一半【由於若是沒超過一半也可能cand爲4,如 [ 4,3,4,5]】
def printHalfMajor(arr): if arr == None or len(arr) == 0: print("No such number!") return False cand = 0 time = 0 for i in range(len(arr)): if time == 0: cand = arr[i] time += 1 elif cand == arr[i]: time += 1 else: time -= 1 time = 0 for i in range(len(arr)): if arr[i] == cand: time += 1 if time > len(arr)//2: return True else: return False arr=[4,3,4,3,4,6,5,4] printHalfMajor(arr)
一個map記錄K個不一樣的數,一旦map大小==k-1,且下一個arr[i]不在map中,就能夠開始刪除map中K個不一樣值。
def printHalfMajor(arr,k): if arr == None or len(arr) <= k: print("No such number!") return False #重點:每次刪除K種不一樣的值【採用字典存儲K種不一樣的值】 map = {} for i in range(len(arr)): if arr[i] in map: map[arr[i]] += 1 else: if len(map) == k-1: for key in list(map): map[key] -= 1 if map[key] == 0: del map[key] else: map[arr[i]] = 1 #查詢map剩餘的數在原數組中的數量 time = 0 flag = False for key in map: for i in range(len(arr)): if arr[i] == key: time += 1 if time > len(arr)//k: flag = True print(key) time = 0 return flag arr=[4,3,4,3,4,6,5,4] K = 3 printHalfMajor(arr,K)
def longestSubArr(arr): if not arr: return 0 res = 0 for i in range(len(arr)): for j in range(i,len(arr)): if isValid(arr[i:j+1]): res = max(res,j - i + 1) return res def isValid(arr): sortArr = sorted(arr) for i in range(len(sortArr)-1): if sortArr[i] != sortArr[i+1] - 1: return False return True arr = [5,5,3,2,6,4,3] longestSubArr(arr)
def two(arr,k): if not arr or len(arr)<2: return None res = [] left = 0 right = len(arr) - 1 while left < right: if arr[left] + arr[right] == k: if left == 0 or left > 0 and arr[left] != arr[left-1]: print(arr[left],arr[right]) left += 1 right -= 1 elif arr[left] + arr[right] < k: left += 1 elif arr[left] + arr[right] > k: right -= 1 arr=[-8,-4,-3,0,1,2,4,5,8,9] k=10 two(arr,k)
def two(arr,f,l,r,k): while l < r: if arr[l] + arr[r] < k: l += 1 elif arr[l] + arr[r] > k: r -= 1 else: if l == f+1 or arr[l-1] != arr[l]: print(arr[f], ',' , arr[l] , ',' , arr[r]) l += 1 r -= 1 def three(arr,k): if not arr or len(arr) < 3: return False for i in range(len(arr)): if i == 0 or arr[i] != arr[i-1]: two(arr,i,i+1,len(arr)-1,k-arr[i]) arr = [-8,-4,-3,0,1,2,4,5,8,9] k = 10 three(arr,k)
考慮N個數的數組A中是否存在和爲K的解,能夠分爲考慮(N-1個數中是否有和爲K的解)或者(N-1個數中是否有和爲K-A[N-1]的解(解包含A[N-1]的狀況))。
也就是說,動態規劃方程是:P[n][k]=P[n-1][k] || P[n-1][ k-arr[n-1] ];
另外一種解法:https://www.tuicool.com/articles/eEfe2mf【採用棧】
給定一個數組arr,該數組無序,但每一個值爲正數,再給定一個正數k。求arr的全部子數組中全部元素相加和爲k的最長子數組長度。
例如,arr=【1,2,1,1,1】,k=3。
累加和爲3的最長子數組爲【1,1,1】,因此結果爲3
設置兩個指針變量left,right。遍歷數組,直到 right < len(arr)。不用擔憂left,由於只要left>right,下一步right就會+1.初始狀態,二者都爲0。
變量lrsum記錄,left到right的和。變量res記錄結果,即=k的子數組最長長度。
res = max(res,right - left +1)
lrsum -= arr[left]
left += 1
right += 1
若right==len(arr):break
lrsum += arr【right】
lrsum -= arr[left]
left += 1
def getMaxlen(arr,k): if not arr or len(arr)<1: return 0 left , right = 0 , 0 res , lrsum = 0 , arr[0] while right < len(arr): if lrsum == k: res = max(res,right - left + 1) lrsum -= arr[left] left += 1 elif lrsum < k: right += 1 if right == len(arr): break lrsum += arr[right] else: lrsum -= arr[left] left += 1 arr = [2,2,9,2] k = 4 getMaxlen(arr,k)
題目:
給定一個無序數組arr,其中元素可正、可負、可0,給定一個整數k,求arr全部的子數組中累加和爲k的最長子數組長度。
補充題目:
給定一個無序數組arr,其中元素可正、可負、可0。求arr全部的子數組中正數與負數個數相等的最長子數組長度。
補充題目:
給定一個無序數組arr,其中元素只是1或0,求arr全部的子數組中0和1個數相等的最長子數組長度。
s【i】表明子數組arr【0……i】全部元素的累加和。
arr【j……i】= s【i】- s【j】
題目要求的是若arr【j……i】==k,求最長的j-i+1
好比:arr = 【5,1,2,3,3】,k=6。
s[3] = 11,s[0] =5,sum(arr 【1:3】)= s[3] - s[0] = 6,長度爲3
s[4] = 14,s[2] = 8, sum(arr 【3:4】)= s[4] - s[2] = 6,長度爲2
結果爲3
採用字典存儲s
代碼:
def maxLen(arr,k): if not arr or len(arr) == 0: return 0 dic = {} dic[0] = -1 res , nsum = 0 , 0 for i in range(len(arr)): nsum += arr[i] if (nsum - k) in dic: res = max(i - dic[nsum - k],res) if nsum not in dic: dic[nsum] = i return res arr = [5,1,2,3,3] k = 6 maxLen(arr,k)
給定一個無序數組arr,其中元素可正、可負、可0,給定一個整數k。求arr全部的子數組中累加和小於或等於k的最長子數組長度。
例如:arr = [3,-2,-4,0,6],k = -2,相加和小於或等於-2的最長子數組爲{3,-2,-4,0},因此結果返回4。
題目要求的是:若arr【i……j】<= k,求最長的j-i+1。
arr【i……j】 = s[j] - s[i] ,(s[i] 表示 arr[0……i] 的值)
故判斷 s[j] - s[i] <= k,即 判斷 s[j] - k <= s[i]。
對於s[j] - k 找到第一個s[i] >= s[j] - k,就是最長的j-i+1。故建立一個輔助的列表helper,存儲s[i] 當前出現的最大值。例如:arr = [1,2,-1,5,-2],k= -2 ,則 s[i] 列表爲 [ 0,1,3,2,7,5],則helper = 【0,1,3,3,7,7】
好比當 j = 3時,【查找用二分法,時間複雜度爲O(logN)】要找到 比 arr[3] - k = 5 大的第一個 s[i] 所在的位置i,所求的結果就爲 j - i+ 1。藉助helper輔助列表可知,第一個比5大的數爲7,在 i = 4的位置,此時 表示遍歷到 j = 3但只有在i=4時才能找到比5大的數,故j-i+1=0表示 arr【0……3】沒有比 k小於或等於的數。
總結步驟:
一、建立一個輔助列表。
二、遍歷數組,計算s[i] ,採用二分法查找輔助列表,找到第一個比s[i] - k大的數。
def maxLen(arr,k): if not arr or len(arr) <= 0: return 0 helper = [0] * (len(arr)+1) nsum = 0 for i in range(len(arr)): nsum += arr[i] helper[i+1] = max(nsum,helper[i]) nsum = 0 res = 0 pre = 0 nlen = 0 for i in range(len(arr)): nsum += arr[i] tmp = getcurMax(helper,nsum - k) nlen = 0 if tmp == -1 else (i-tmp + 1) res = max(res,nlen) return res def getcurMax(arr,nsum): left = 0 right = len(arr) - 1 res = -1 while left <= right: mid = (left + right) //2 if arr[mid] >= nsum: right = mid - 1 res = mid else: left = mid + 1 return res arr = [-1,-2,-1,-5,-2] k = -2 maxLen(arr,k)
給定一個長度不小於2的數組arr,實現一個函數調整arr,要麼讓全部的偶數下標都是偶數,要麼讓全部的奇數下標都是奇數。
設置三個變量,even下標、odd下標、end下標
只要arr【end】 是偶數,就將arr【end】和arr【even】交換,even+=2.
一樣,arr【end】 是奇數,就將arr【end】和arr【odd】交換,odd+=2.
def test(arr): if not arr or len(arr) <= 1: return arr even = 0 odd = 1 end = len(arr) - 1 while even < len(arr) and odd < len(arr): if arr[end] % 2 == 0: arr[end] , arr[even] = arr[even] , arr[end] even += 2 elif arr[end] % 2 == 1: arr[end] , arr[odd] = arr[odd] , arr[end] odd += 2 return arr arr = [1,8,3,2,4,6] test(arr)
給定一個數組arr,返回子數組的最大累加和。
例如,arr= 【1,-2,3,5,-2,6,-1】,全部的子數組中,【3,5,-2,6】能夠累加出最大的和12,因此返回12.
import sys def test(arr): if not arr or len(arr) == 0: return 0 res = -sys.maxsize cur = 0 for i in range(len(arr)): cur += arr[i] res = max(res,cur) cur = 0 if cur<0 else cur return res arr = [1,-2,3,5,-2,6,-1] test(arr)
給定一個矩陣matrix,其中的值有正、有負、有0,返回子矩陣的最大累加和。
例如,矩陣matrix爲:
對於每一行都有如下操做:for i in range(len(arr))
for j in range(i ,len(arr)):
【64,-40,64】
【-81,-7,66】
變成 s =【-17,-47,130】,此時該子數組最大和爲130【for k in range(len(arr[0]))】
import sys def maxSum(arr): if not arr or len(arr) == 0 or len(arr[0]) == 0: return 0 res = - sys.maxsize cur = 0 for i in range(len(arr)): s = [0] * len(arr[0]) for j in range(i , len(arr)): cur = 0 for k in range(len(arr[0])): s[k] += arr[j][k] cur += s[k] res = max(res,cur) cur = 0 if cur < 0 else cur return res arr = [[-90,48,78],[64,-40,64],[-81,-7,66]] maxSum(arr)
def maxMul(arr): if not arr or len(arr) == 0: return 0 maxMul = arr[0] minMul = arr[0] res = 0 for i in range(1,len(arr)): maxMul = maxMul * arr[i] minMul = minMul * arr[i] maxMul = max(maxMul , minMul ,arr[i] ) minMul = min(maxMul , minMul , arr[i] ) res = max(res , maxMul) return res
找到三個最大的數max1,max2,max3 和兩個最小的數 min1 ,min2 ,min3 ,返回 max( max1*max2*max3 , max1 * min1 * min2)
給定一個N*M的矩陣matrix, 在這個矩陣中, 只有0和1兩種值, 返回邊框全是1的最大正方
形的邊長長度。
例如:
0 1 1 1 1
0 1 0 0 1
0 1 0 0 1
0 1 1 1 1
0 1 0 1 1
其中, 邊框全是1的最大正方形的大小爲4*4, 因此返回4
1.矩陣中一共有N*N個位置。O(N2)
2.對每個位置均可以成爲邊長爲N~1的正方形左上角。好比,對於(0,0)位置,依次檢查是不是邊長爲5的正方形的左上角,而後檢查邊長爲四、3等。O(N)
3.如何檢查一個位置是否能夠成爲邊長爲N的正方形的左上角?遍歷這個邊長爲N的正方形邊界看是否只由1組成,也就是走過四個邊的長度(4N)。O(N)
總的時間複雜度:O(N2)*O(N)*O(N)=O(N4)
用與原矩陣一樣大小的兩個矩陣,一個爲right,一個爲down,
right[i][j]的值表示從位置(i,j)向右出發有多少個連續的1。
down[i][j]的值表示從位置(i,j)向下出發有多少個連續的1。
right和down的計算過程:從右到左,從下到上依次填好兩個矩陣。
給定一個整型數組arr,返回不包含本位置值的累乘數組。
例如,arr = [2, 3, 4, 1],返回[12, 8, 24, 6],即除本身之外,其餘位置上的累乘。
【要求】
分別使用輔助兩個數組left和right,其中left表示數組從左到右的累乘結果(即left[i] = arr[0…i]的累乘);相反,right表示數組從右到左的累乘結果。那麼對於結果數組res,res[i] = left[i-1] * right[i+1]。
實際上,並不須要額外聲明兩個輔助數組。能夠複用結果數組res,即先將res當輔助數組用,再把res調整爲結果數組便可。具體實現見以下代碼:
def product2(arr): if arr == None or len(arr) < 2: return res = [0 for i in range(len(arr))] res[0] = arr[0] for i in range(1, len(res)): res[i] = res[i-1] * arr[i] tmp = 1 for i in range(len(arr)-1, 0, -1): res[i] = res[i-1] * tmp tmp *= arr[i] res[0] = tmp return res arr = [2,3,1,4] product2(arr)
給定一個有序數組arr,調整arr使得這個數組的左半部分沒有重複部分且升序,而不用保證右部分是否有序。
例如:arr=[1,2,2,2,3,3,4,5,6,6,7,7,8,8,9,9],調整以後arr=[1,2,3,4,5,6,7,8,9…]。
時間複雜度O(N),額外空間複雜度O(1)
思路:兩個變量
變量u表示:arr[0……u]上是無重複且升序的,初始u=0
變量i表示:arr[u+1……i]不保證無重複但升序的區域,i是遍歷到的結果,初始時i=1.
i向右移動,若arr【i】!=arr【u】,則將arr【i】加入arr【0……u】區域內,即arr【u+1】和arr【i】交換。
直到遍歷結束
代碼:
def patition(arr): if not arr or len(arr)==1: return arr u , i = 0 , 1 while i < len(arr): if arr[i] != arr[u]: arr[i] , arr[u+1] = arr[u+1] , arr[i] u += 1 i += 1 return arr arr = [1,2,2,2,3,3,4,5,5,6,6,7,8,9,9] patition(arr)
給定一個數組arr,其中只可能含有0、一、2三個值,請實現arr的排序。
另一種問法:有一個數組,其中只有紅球、籃球和黃球,請實現紅球全放在數組的左邊,籃球放在中間,黃球放在右邊。
另一種問法:有一個數組,再給定一個值K,請實現比K小的數都放在數組的左邊,等於K的值都放在數組的中間,比K大的數都放在數組的右邊。
left變量:表示左區arr【0……left】都是0,left初始爲-1
index變量:表示中區arr【left+1……index】都是1,index初始爲0
right變量:表示右區arr【right……N-1】都是2,right初始爲N-1.
index表示從左往右遍歷的位置:
arr【index】== 1,留在中區,index+=1
arr【index】==0,加入左區,即arr【left+1】和arr【index】交換,left+=1,index+=1
arr【index】== 2,加入右區,即arr【right-1】和arr【index】交換,right-=1。
當index == right,中止遍歷,由於中區和右區對接了。
def patition(arr): if not arr or len(arr)==1: return arr left , index , right = -1 , 0 , len(arr) while index != right: if arr[index] == 0: arr[left+1] , arr[index] = arr[index] , arr[left+1] left += 1 index += 1 elif arr[index] == 1: index += 1 elif arr[index] == 2: arr[right - 1] , arr[index] = arr[index] , arr[right-1] right -= 1 return arr arr = [1,0,2,2,1,1,0,2,1,2] patition(arr)
給定一個無序整型數組arr,找到數組中未出現的最小正整數。
舉例:
arr = 【-1,2,3,4】。返回1
arr = 【1,2,3,4】。返回5.
分析:
假如arr有序,則:
(1) arr爲整數1,2,3…N,N+2,N+3……的一個隨機排列,那個未出現的最小正整數就是N+1。
【設置left變量表示已經有序的N個數 arr [0:N-1] 】
(2) arr中有小於1或者大於N或者重複的數出現(咱們稱之爲「不合法」的數),則未出現的最小正整數必定在1到N中間(由於數組一共只有N個數,若是出現不合法的數,則出現的1到N之間的數的個數必定小於N,故必定有沒有出現的數)。
【設置right變量,初始N+2, 表示還能夠有序的arr [ N:N+2 ]】
【好比:發現 arr[N](即N+2)合法但位置不理想,將N+2換到它理想的位置,而後將N+3換到該位置 arr[ N ],繼續比較N+3是否是合法且理想,發現並不合法,合法區間right-1變成 arr[ N:N+1 ] 】
作法:
(1) 先設置兩個變量L,R。初始值:L=0,R=len(arr)
也就是說,1到L上的數已經出現,[L+1,R]區間上的數未出現但可能會出現。
(2)遍歷數組:
1》當 L 的位置值等於L+1,表示獲得想要的,故L ++
2》三種不合法狀況:都需R--
3》合法但位置不理想:else,將 arr【L】 交換到理想位置,理想位置的值換到 L 位置來,繼續判斷 L 位置的值。
def missNum(arr): if not arr: return 1 left , right = 0 , len(arr) while left < right: if arr[left] == left + 1: left += 1 elif arr[left] <= left or arr[left] > right or arr[left] == arr[arr[left]-1]: right -= 1 arr[left] = arr[right] #right-=1後合法區域不包括arr【right】了,將arr[right]換到left位置繼續判斷 else: #arr[left]理想位置爲arr[left]-1,將arr[arr[left]-1]換到left位置繼續判斷 arr[left] , arr[arr[left] - 1] = arr[arr[left]-1] , arr[left] return left + 1 arr = [1,3,-2,4,5] missNum(arr)
在一個二維座標數組中,第一列x爲座標值,第二列y爲金額,求知足|x1-x2| >= d,求(y1 + y2)和最大的值。【兩個變量知足座標值大於等於d條件,且其金額之和最大】,返回金額和的值。
如:d = 3 , 輸入 [[1,1],[3,5],[4,8],[6,4],[10,3],[11,2]]。輸出:11,由於 [4,8] 和[10,3],|4 - 10| >= d, 8 + 3 =11金額最大。
思路:
先將座標排序,而後將金額從後面開始,從大到小放入棧中。
接着,從前日後遍歷,採用一個prefix存儲前面的最大值,同時一旦遇到知足d條件的棧中的第一個數,更新和最大值。
代碼
def solve(arr,d): #將arr按座標值排序 arr.sort(); #suffix是將arr按金額從大到小存入棧中,如arr中金額爲[1,5,8,3,4,2] ,則suffix爲[8,8,8,4,4,2] suffix = [0] * len(arr) suffix[len(arr) - 1] = arr[len(arr) - 1][1] for i in range(len(arr) - 2,-1,-1): suffix[i] = suffix[i + 1] if suffix[i + 1] > arr[i][1] else arr[i][1] #prefix存前面最大的數 prefix = 0 # pos爲當前第一個知足arr[pos] > arr[i]的數 pos = 0 ret = 0 for i in range(len(arr)): prefix = prefix if prefix > arr[i][1] else arr[i][1] while pos < len(arr) and arr[pos][0] - arr[i][0] < d: pos += 1 if pos < len(arr): ret = ret if ret > prefix +suffix[pos] else prefix + suffix[pos] return ret arr = [[1,1],[3,5],[4,8],[6,4],[10,3],[11,12]] d = 3 solve(arr,d)
輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得全部的奇數位於數組的前半部分,全部的偶數位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。
def reOrderArray(self, array): # write code here if len(array) <= 1: return array flag = -1 for i in range(len(array)): if (array[i] % 2 == 0) and flag == -1: flag = i elif (array[i] % 2 == 1) and flag != -1: array.insert(flag,array[i]) flag += 1 del array[i+1] return array
在數組中的兩個數字,若是前面一個數字大於後面的數字,則這兩個數字組成一個逆序對。輸入一個數組,求出這個數組中的逆序對的總數P。並將P對1000000007取模的結果輸出。 即輸出P%1000000007
輸入:1,2,3,4,5,6,7,0
輸出:7
遍歷兩遍,針對每個數都找後面比其小的數。
逆序對的總數=左邊數組中的逆序對的數量+右邊數組中逆序對的數量+左右結合成新的順序數組時中出現的逆序對的數量
class Solution: def __init__(self): self.P = 0 def InversePairs(self, data): # write code here if not data: return 0 def merge(arr1,arr2): res = [] i , j = 0 , 0 while i < len(arr1) and j < len(arr2): if arr1[i] <arr2[j]: res.append(arr1[i]) i += 1 else: res.append(arr2[j]) j += 1 self.P += (len(arr1)-i) res.extend(arr1[i:]) res.extend(arr2[j:]) return res def fen(data): if len(data)<=1: return data mid = len(data)//2 left = fen(data[:mid]) right = fen(data[mid:]) return merge(left,right) fen(data) return self.P % 1000000007
思路1:離散化 + 樹狀數組
能夠把數一個個插入到樹狀數組中, 每插入一個數, 統計比他小的數的個數,對應的逆序爲 i- getsum( data[i] ),其中 i 爲當前已經插入的數的個數, getsum( data[i] )爲比 data[i] 小的數的個數,i- getsum( data[i] ) 即比 data[i] 大的個數, 即逆序的個數。最後須要把全部逆序數求和,就是在插入的過程當中邊插入邊求和。
代碼:
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <string.h> using namespace std; const int maxn=500005; int n;int aa[maxn]; //離散化後的數組 int c[maxn]; //樹狀數組 struct Node{ int v; int order; } in[maxn]; int lowbit(int x){ return x&(-x); } void update(int t,int value){ int i; for(i=t;i<=n;i+=lowbit(i)) { c[i]+=value; } } int getsum(int x){ int i; int temp=0; for(i=x;i>=1;i-=lowbit(i)) { temp+=c[i]; } return temp; } bool cmp(Node a ,Node b){ return a.v<b.v; } int main(){ int i,j; while(scanf("%d",&n)==1 && n) { //離散化 for(i=1;i<=n;i++) { scanf("%d",&in[i].v); in[i].order=i; } sort(in+1,in+n+1,cmp); for(i=1;i<=n;i++) aa[in[i].order]=i; //樹狀數組求逆序 memset(c,0,sizeof(c)); long long ans=0; for(i=1;i<=n;i++) { update(aa[i],1); ans+=i-getsum(aa[i]); } cout<<ans<<endl; } return 0; }
另外一種思路:
這樣直到把最小元素放完,累加每次放元素是該元素前邊已放元素的個數,這樣就算出總的逆序數來了
在統計和計算每次放某個元素時,該元素前邊已放元素的個數時若是一個一個地數,那麼一趟複雜度爲O(n),總共操做n趟,複雜度爲O(n^2),和第一種方法的複雜度同樣了,那咱們爲何還用這麼複雜的方法
固然,在每次統計的過程當中用樹狀數組能夠把每一趟計數個數的複雜度降爲O(logn),這樣整個複雜度就變爲O(nlogn)
將序列中的每一個數按照從大到小的順序插入到樹狀數組中,給當前插入節點及其父節點的個數加1,而後統計該節點下邊及右邊放置元素的個數
題意:一維線性的直線上,排列着n個兵營,初始每一個兵營有固定的人數,有兩個操做:一個是添加,把某個兵營增長人數d;二是詢問,求某兩個兵營之間全部兵營的總人數之和。