[34]四数相加 II 和 盛最多水的容器
四数相加 II
题目要求
给你四个整数数组 nums1、nums2、nums3 和 nums4 ,数组长度都是 n ,请你计算有多少个元组 (i, j, k, l) 能满足:
0 <= i, j, k, l < n
nums1[i] + nums2[j] + nums3[k] + nums4[l] == 0
思路
哈希表查询,把4个数组的问题拆分为两个,这样循环的复杂度会低一些。
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
#countAB = collections.Counter(u + v for u in A for v in B)
count = 0
hashMap = {}
for i in range(len(nums1)):
for j in range(len(nums2)):
if not nums1[i] + nums2[j] in hashMap:
hashMap[nums1[i] + nums2[j]] = 1
else:
hashMap[nums1[i] + nums2[j]] = hashMap[nums1[i] + nums2[j]] + 1
for i in range(len(nums3)):
for j in range(len(nums4)):
if (-(nums3[i] + nums4[j])) in hashMap:
count = count + hashMap[-(nums3[i] + nums4[j])]
return count
盛最多水的容器
题目要求
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
返回容器可以储存的最大水量。
说明:你不能倾斜容器
示例 1:
输入:[1,8,6,2,5,4,8,3,7]
输出:49
解释:图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
思路
用一个双循环来找到最大的面积,理论上来说是可行的,但是会超时。。。
考虑第一步,假设当前左指针和右指针指向的数分别为 x x x 和 y y y,不失一般性,我们假设 x ≤ y x \leq y x≤y。同时,两个指针之间的距离为 t t t。那么,它们组成的容器的容量为:
m
i
n
(
x
,
y
)
∗
t
=
x
∗
t
min(x,y)\ast t=x\ast t
min(x,y)∗t=x∗t
我们可以断定,如果我们保持左指针的位置不变,那么无论右指针在哪里,这个容器的容量都不会超过
x
∗
t
x\ast t
x∗t 了。注意这里右指针只能向左移动,因为 我们考虑的是第一步,也就是 指针还指向数组的左右边界的时候。
我们任意向左移动右指针,指向的数为 y 1 y_1 y1,两个指针之间的距离为 t 1 t_1 t1,那么显然有 t 1 < t t_1<t t1<t,并且 m i n ( x , y 1 ) ≤ m i n ( x , y ) min(x,y_1) \leq min(x,y) min(x,y1)≤min(x,y):
如果 y 1 ≤ y y_1\leq y y1≤y,那么 m i n ( x , y 1 ) ≤ m i n ( x , y ) min(x,y_1)\leq min(x,y) min(x,y1)≤min(x,y);
如果 y 1 > y y1>y y1>y,那么 m i n ( x , y 1 ) = x = m i n ( x , y ) min(x,y_1)=x=min(x,y) min(x,y1)=x=min(x,y)。
因此有:
m
i
n
(
x
,
y
t
)
∗
t
1
<
m
i
n
(
x
,
y
)
∗
t
min(x,y_t)\ast t_1<min(x,y)\ast t
min(x,yt)∗t1<min(x,y)∗t
即无论我们怎么移动右指针,得到的容器的容量都小于移动前容器的容量。也就是说,这个左指针对应的数不会作为容器的边界了,那么我们就可以丢弃这个位置,将左指针向右移动一个位置,此时新的左指针于原先的右指针之间的左右位置,才可能会作为容器的边界。
class Solution:
def maxArea(self, height: List[int]) -> int:
maxArea = 0
left = 0
right = len(height) - 1
while left < right:
area = (right - left) * min(height[right], height[left])
if maxArea < area:
maxArea = area
if height[left] > height[right]:
right = right - 1
else:
left = left + 1
return maxArea