今日题号:11,14,15
题 011.盛水最多的容器
题意
给定一个数组,从中取出两个数,视作盛水容器的两边,将两数之间的距离视作容器的底部,求能使容器容积最大的两个数。
eg.
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
解释: 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
解题思路
本题求得实际上就是 min(左高度,右高度)*左右间距 的最大值
如同许多优秀题解的方法,双指针是一种理解较为容易且容易实施的方案,具体实施方法如下:
- 考虑到题目实际上就是求一个矩形的面积,所以首先令一边达到最长。即从数组的左右两端往中间移动,不断更新容积的最大值
- 每次判断左右两边那个更小,如同水桶定律,水桶装多少取决于它最短的那根板,所以找到二者中更小的那个数,比较当前容积和目前最大值
- 比较后,从数值更小的一侧向内推进
- 两点相遇后,循环结束
代码
def maxArea(self,height:List[int])->int:
left,right=0,len(height)-1
res=0
while left<right:
if height[left]<height[right]:
res=max(res,height[left]*(right-left))
left+=1
else:
res=max(res,height[right]*(right-left))
right-=1
return res
题 014.最长公共前缀
题意
从一个字符串数组中找到最长公共前缀,若不存在返回空字符串。
解题
本题比较简单,因为求的是整个数组中的所有字符串的公共前缀,所以只要比较字典序最大和最小的两个。
利用max和min函数找到数组中字典序最大和最小值,找到这两个字符串的最长公共前缀即可。
关键代码
#字典序最小x,最大y
for i in range(len(x)):
if x[i]!=y[i]:
return x[:i]
return x
题 015.三数之和
题意
对于一个由整数构成的数组,求其中是否存在三个数,它们的和为0,若存在,返回所有这样的组合。(不可以重复)
eg.
输入: nums = [-1,0,1,2,-1,-4]
输出: [[-1,-1,2],[-1,0,1]]
解题思路
参考部分题解,双指针方法效率较高。
具体做法是:
- 先将数组进行排序
- 针对第一个数进行循环
- 每循环到一个数
- 对于后两个数分别作为指针,从剩余数组的两端向内压缩,进行查找
- 当三个数的和为零时,将答案储存
- 针对后两个数(即两个指针),继续向内压缩,并确保不会重复
- 第一个数使用完后,确保下一个数与它不同,不然会出现重复的情况,具体的做法是
if k>0 and nums[k]==nums[k-1]:
continue
- 如果嫌以上提到的避免重复的操作麻烦,可以换种思路,将答案res暂时定义为set类型,这样遍历时不管有没有重复通通add进去,最后输出时再用
list(res)
转为list类型
代码
def threeSum(self, nums: List[int]) -> List[List[int]]:
m=len(nums)
if m<3:
return []
nums.sort()
res=[]
for k in range(m-2):#第一个数顶多遍历到第m-3位
if nums[k]>0: break#若第一个数大于0,则不可能是答案
if k>0 and nums[k]==nums[k-1]:#从第一个数的角度避免重复
continue
i,j=k+1,m-1
while i<j:
sum=nums[i]+nums[j]+nums[k]
#向内压缩
if sum>0:
j-=1
elif sum<0:
i+=1
else:
res.append([nums[k],nums[i],nums[j]])
#避免后两个数的重复
while i<j and nums[i]==nums[i+1]:
i+=1
while i<j and nums[j]==nums[j-1]:
j-=1
i+=1
j-=1
return res