阿里筆試題(2017線上程式設計題)-- 數串分組
阿新 • • 發佈:2019-02-09
題目
2017年3月阿里線上程式設計題(實習內推)
給定一串數字
判斷是否存在這三個元素,它們將數字串分為四個子串,其中每個子串的數字之和均相同(該3個元素不納入計算)
要求時間複雜度和空間複雜度均不能超過O(n)
實現
python 寫的
程式碼不夠優美,歡迎留言指正!
注:添加了測試程式碼,所以比較冗長!
# -*- encoding:utf-8 -*-
class StrSplit(object):
def __init__(self, srclist):
self.srclist = srclist
self.sumA = [0 ] * len(self.srclist) # 儲存從左到右依次累積統計的sum
self.sumB = [0] * len(self.srclist) # 儲存從右到左依次累積統計的sum
self.dictA = {} # 儲存sumA中具有某個值的索引號
# 如dictA[100]為[1,12],即表示sumA[1]和sum[12]都是100
self.dictB = {} # 儲存sumB中具有某個相同索引號
self.result = [0, 0, 0] # 儲存統計結果,即需要刪除的三個元素的索引
self.initstrsplit()
def initstrsplit(self):
sum = 0
for i in range(0, len(self.srclist)):
sum += self.srclist[i]
self.sumA[i] = sum
if self.sumA[i] in self.dictA:
self.dictA[self.sumA[i]].append(i)
else :
self.dictA[self.sumA[i]] = [i]
sum = 0
for i in range(len(self.srclist)-1, -1, -1):
sum += self.srclist[i]
self.sumB[i] = sum
if self.sumB[i] in self.dictB:
self.dictB[self.sumB[i]].append(i)
else:
self.dictB[self.sumB[i]] = [i]
def getmidpivot(self, left, right, partsum):
if not (1 < left < right < len(self.srclist)-2 and left < right - 1):
return False
#print "left:%d, right:%d, partsum:%d" %(left, right, partsum)
mid = self.sumA[left-1] + partsum # left-1為要刪除的第一個元素
if mid in self.dictA:
for i in self.dictA[mid]: # i+1 為要刪除的中間元素
if left-1 < i < right-1:
#print self.sumA[right], self.sumA[i]
if self.sumA[right] - self.sumA[i+1] == partsum:
return i+1
else:
continue
return False
def getresult(self):
if len(self.srclist) < 7:
return False
for i in range(0, len(self.sumA)-4):
if self.sumA[i] in self.dictB:
index = self.dictB[self.sumA[i]] # index is list type
for j in index:
if j > i+3:
# 刪除元素i+1 和 j-1後, 判斷是否存在中間元素
m = self.getmidpivot(i+2, j-2, self.sumA[i])
if m:
self.result = [i+1, m, j-1]
return True
return False
def checkresult(self):
sum1, sum2, sum3, sum4 = 0, 0, 0, 0
left, mid, right = tuple(self.result)
for i in range(0, left):
sum1 += self.srclist[i];
for i in range(left+1, mid):
sum2 += self.srclist[i];
if sum2 != sum1: return False
for i in range(mid+1, right):
sum3 += self.srclist[i];
if sum3 != sum1: return False
for i in range(right+1, len(self.srclist)):
sum4 += self.srclist[i];
if sum4 != sum1: return False
return True
if __name__ == "__main__":
import random
a = [1,2,3,4,5,6,7,8,9,10,1,2,3,24,3,4,1,3,4,5,3,2,1,2,3,4,5,6,7]
b = [1,1,1,9,1,2,3,-3,4,1,2,5,1,2,-100,100,2,3,-5]
c = [1,1,1,1,1,1,1]
d = []
e = [0,0,0,0,0,0,0,0,0,0]
all = [a, b, c, d, e]
for i in range(0, 100): # 列表數
tmp = []
for j in range(0, random.randint(1, 1000)): # 元素的個數
tmp.append(random.randint(-10, 10)) # 元素的範圍
all.append(tmp)
okcount = 0
failcount = 0
errorcount = 0
for i in all:
swf = StrSplit(i)
# print swf.srclist
ret = swf.getresult()
if ret:
okcount += 1
if not swf.checkresult(): errorcount += 1
print " StrSplit: True "
print " Result: ", swf.result
print " Check result: ", swf.checkresult()
else:
failcount += 1
print " SUCCESS COUNT: ", okcount
print " FAILED COUNT: ", failcount
print " ERROR COUNT: ", errorcount