由于本人之前一直是按照顺序,每天一道,但目前在刷腾讯精选50道,所以暂时就不按照顺序刷了,刷完腾讯精选50道之后在按照顺序开始刷。以下代码全部基于Python,后续会补齐C、Java、R、C++版本。
-
第0011题目:盛水最多的容器
给你 n 个非负整数 a1,a2,…,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0) 。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器。
思路:双指针法,大致流程: 设置双指针 ii,jj 分别位于容器壁两端,根据规则移动指针,并且更新面积最大值 res,直到 i == j 时返回 res。
指针移动规则与证明: 每次选定围成水槽两板高度 h[i]h[i],h[j]h[j] 中的短板,向中间收窄 1 格。以下证明:
设每一状态下水槽面积为 S(i, j)S(i,j),(0 <= i < j < n)(0<=i<j<n),由于水槽的实际高度由两板中的短板决定,则可得面积公式 S(i, j) = min(h[i], h[j]) × (j - i)S(i,j)=min(h[i],h[j])×(j−i)。
在每一个状态下,无论长板或短板收窄 1 格,都会导致水槽 底边宽度 −1:
若向内移动短板,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 可能变大,因此水槽面积 S(i, j)S(i,j) 可能增大。
若向内移动长板,水槽的短板 min(h[i], h[j])min(h[i],h[j]) 不变或变小,下个水槽的面积一定小于当前水槽面积。
因此,向内收窄短板可以获取面积最大值代码:
class Solution: def maxArea(self, height) -> int: i, j, res = 0, len(height) - 1, 0 while i < j: if height[i] < height[j]: res = max(res, height[i] * (j - i)) i += 1 else: res = max(res, height[j] * (j - i)) j -= 1 return res a = [1, 8, 6, 2, 5, 4, 8, 3, 7] s = Solution() result = s.maxArea(a) print(result)
结果:
-
0014:最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""。 思路:利用python独有的zip特性,解释如下: Python3 zip() 函数 函数描述: zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。 我们可以使用 list() 转换来输出列表。 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。案例如下: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210113154620938.png) 其中*str是解包的意思,可以将一个字符串列表解开,效果如下: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210113154137295.png) 代码: ```python class Solution: def longestCommonPrefix(self, strs): """ :type strs: List[str] :rtype: str """ res = "" for tmp in zip(*strs): tmp_set = set(tmp) if len(tmp_set) == 1: res += tmp[0] else: break return res s = ["flower", "flow", "flight"] a = Solution() sum = a.longestCommonPrefix(s) print(sum) ``` 结果:![在这里插入图片描述](https://img-blog.csdnimg.cn/20210113145955824.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NhbmR5bHg=,size_16,color_FFFFFF,t_70) 另一种方法,是端点比较法。在python中,字符串是可以用来比较大小的,只根据ASCI码值来比较大小的。我们只需找出最大的字符串和最小的字符串即可,然后比较这两个字符串的公共前缀即可。 代码: ```python def longestCommonPrefix(strs): if not strs: return "" s1 = min(strs) s2 = max(strs) for i, x in enumerate(s1): if x != s2[i]: return s1[:i] return s1 s = ["flower", "flow", "flight"] print(longestCommonPrefix(s)) ``` 结果:
-
0015:三数之和
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。代码和思路:
```python class Solution: def threeSum(self, nums): n=len(nums) res=[] # 特判,对于数组长度n,如果数组为null或者数组长度小于3,返回[] if(not nums or n<3): return [] #排序 nums.sort() res=[] #遍历 for i in range(n): #若nums[i] > 0,所以后面都是正数,不可能有三个数加和等于0,直接返回结果 if(nums[i]>0): return res #如果nums[i]有重复,直接continue if(i>0 and nums[i]==nums[i-1]): continue #移动指针 L=i+1 R=n-1 #如果左指针小于右指针,进行判断 while(L<R): if(nums[i]+nums[L]+nums[R]==0): res.append([nums[i],nums[L],nums[R]]) #去重 while(L<R and nums[L]==nums[L+1]): L=L+1 # 去重 while(L<R and nums[R]==nums[R-1]): R=R-1 L=L+1 R=R-1 #如果和大于0,说明右指针过大,需要缩小右边指针的位置,即向左移动 elif(nums[i]+nums[L]+nums[R]>0): R=R-1 else: L=L+1 return res ``` 结果:![在这里插入图片描述](https://img-blog.csdnimg.cn/20210113153609115.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0NhbmR5bHg=,size_16,color_FFFFFF,t_70)