略带减少负担的暴力法
def maxArea(height: list)->int:
left = (1, height[0])
right = (2, height[1])
size = calSize(left, right)
saveList = []
if height[0] > height[1]:
saveList.append(left)
else:
saveList.append(right)
x = 2
for y in height[2:]:
x += 1
now = (x, y)
if y >= max(left[1], right[1]):
saveList.append(now) # 保存高于现在使用高的点
leftSize = calSize(left, now)
rightSize = calSize(right, now)
if leftSize > size or rightSize > size:
if leftSize > rightSize:
size = leftSize
right = now
else:
size = rightSize
left = right
right = now
for highSave in saveList[:-1]:
if calSize(highSave, now) > size:
left = highSave
right = now
size = calSize(left, right)
print(size)
print(left)
print(right)
print(calSize(left, right))
print(saveList)
return size
def calSize(left, right):
bottom = (right[0] - left[0])
height = min(left[1], right[1])
# size = height * bottom
return height * bottom # size
双指针法
def maxArea(height: list)->int:
indexLeft=1
indexRight=len(height)
left = (indexLeft, height[indexLeft-1])
right = (indexRight, height[indexRight-1])
sizeMax=0
while indexRight>indexLeft:
size = calSize(left, right)
if size>sizeMax:
sizeMax=size
if left[1]<right[1]:
indexLeft+=1
left = (indexLeft, height[indexLeft-1])
else :
indexRight-=1
right = (indexRight, height[indexRight-1])
return sizeMax
def calSize(left, right):
bottom = (right[0] - left[0])
height = min(left[1], right[1])
# size = height * bottom
return height * bottom # size
暴力法的时间复杂度为o(n2)
空间复杂度为o(1)以上
本人写的暴力法只计算了目前循环到的点与原来的左右俩边界的面积以及保存的比原来俩边界高的点的值
所以如果最好情况,也是有可能只用计算2n次,最差状态是每个点都比前面的高一点,此时我的复杂度甚至会比普通暴力法更高(有重复计算)
所以出现了双指针法:
时间复杂度为o(n)一次扫描
空间复杂度为o(1)
双指针法适用的原因:(双指针原理)
要面积更大,唯有底或高更长,从头尾两边开始,保证了从底最长到底最短,
然后每次将高度更短的往里移动指针,保证了最高高度
因为如果在木桶短板的高度的状态下乘以可能的最大长度也比之前计算的size小,则不可能在底变小情况下后续比之前的size大,所以可以往里移动较小的高度的指针,指望出现高度更高的情况时有可能乘以较小的底大于之前保存的size