我正在研究中等水平的leetcode问题11。盛水的容器。除了O(n^2)的蛮力解外,还有一个复杂度为O(n)的最优解,它使用容器左右两侧的两个指针。我有点困惑,为什么这个“双指针”方法必须包含最优解。有人知道如何从数学上证明这个算法的正确性吗?这是一个我不知道的算法。非常感谢。
最初的问题是:
给定一个长度为n的整数数组高度。绘制了n条垂直线,使得第i条线的两个endpoint是(i,0)和(i,高度[i])。找到两条与x轴一起构成容器的线,使得容器包含最多的水。返回容器可以存储的最大水量。请注意,您不能倾斜容器。
这个问题的残酷解决方案是(O(n^2)):
def maxArea(self, height: List[int]) -> int:
length = len(height)
volumn = 0
#calculate all possible combinations, and compare one by one:
for position1 in range(0,length):
for position2 in range (position1 + 1, length):
if min(height[position1],height[position2])*(position2 - position1) >=volumn:
volumn = min(height[position1],height[position2])*(position2 - position1)
else:
volumn = volumn
return volumn
最优解方法,我写的代码是这样的(O(n)):
def maxArea(self, height: List[int]) -> int:
pointerOne, pointerTwo = 0, len(height)-1
maxVolumn = 0
#Move left or right pointer one step for whichever is smaller
while pointerOne != pointerTwo:
if height[pointerOne] <= height[pointerTwo]:
maxVolumn = max(height[pointerOne]*(pointerTwo - pointerOne), maxVolumn)
pointerOne += 1
else:
maxVolumn = max(height[pointerTwo]*(pointerTwo - pointerOne), maxVolumn)
pointerTwo -= 1
return maxVolumn
有人知道为什么这种“两指针”方法可以找到最优解吗?谢谢!
非正式的证明可以是这样的:假设我们在到达最佳对之前处于迭代的某个位置:
|
|
|~~~~~~~~~~~~~~~~~~~~~~~|
|~~~~~~~~~~~~~~~~~~~~~~~|
|~~~~~~~~~~~~~~~~~~~~~~~|
|~~~~~~~~~~~~~~~~~~~~~~~|
^ ^
A B
现在,让我们修复A(较小的垂直线),并考虑B剩下的所有选项,我们可以与之配对。很明显,所有这些容器产生的水比我们目前在a和B之间产生的水要少。
因为我们已经说过,我们还没有达到最佳解决方案,很明显,A不能成为促成它的因素之一。因此,我们移动它的指针。
Q、 E.D。
根据我的理解,这个想法大致是:
步骤:
>
如果确实存在内部条形图对,则表示高度高于我们手头的条形图,因此您不应仅将指针向左或向右移动一步,而应将指针向左或向右移动到下一个更高的条形图。
为什么要向左或向右移动指针(以较小者为准)?因为较小的杆无法实现较高杆的“潜力”。
这些步骤背后的核心思想是:从内部捕获最佳解决方案的某个地方开始(步骤1),然后通过每一步,你都会找到一个比现有解决方案更好的解决方案(步骤2和3),最后你会找到最佳解决方案。
剩下一个问题供您思考:当您执行上述步骤时,是什么确保不会错过最佳解决方案?:)
我正在看下面关于极客的问题 给定n个非负整数a_1,a_2,...,a_n其中每个表示坐标(i,a_i)处的一个点。'n'画垂直线,使得线i的两个endpoint在(i,a_i)和(i,0)处。找到两条线,它们与x轴一起构成一个容器,使得容器含有最多的水。 程序应该返回一个整数,该整数对应于可以容纳的水的最大面积(最大面积而不是最大体积听起来很奇怪,但为了简单起见,我们使用的是2D平面)。 问题链
给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 说明:你不能倾斜容器,且 n 的值至少为 2。 图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝
素数分解 整除 最大公约数最小公倍数 1. 生成素数序列 2. 最大公约数 3. 使用位操作和减法求解最大公约数 进制转换 1. 7 进制 2. 16 进制 3. 26 进制 阶乘 1. 统计阶乘尾部有多少个 0 字符串加法减法 1. 二进制加法 2. 字符串加法 相遇问题 1. 改变数组元素使所有的数组元素都相等 多数投票问题 1. 数组中出现次数多于 n / 2 的元素 其它 1. 平方数 2
给定n个非负整数a1, a2,..., an,其中每个表示坐标(i, ai)处的一个点。绘制n条垂直线,使得线i的两个endpoint位于(i, ai)和(i,0)。找到两条线,它们与x轴一起构成一个容器,使得容器中包含最多的水 关于这个问题,我不理解的是,我应该如何知道n条垂直线的y坐标值(高度)。
我对编码和练习leetcode问题还不熟悉。整数反向问题涉及溢出。 我已经搜索并讨论了关于如何处理溢出的大部分内容。有人能解释一下溢出的原因吗?
Leetcode#11盛水的容器 https://leetcode.com/problems/container-with-most-water/ 给定n个非负整数a1, a2,..., an,其中每个表示坐标(i, ai)处的点。绘制n条垂直线,使得线i的两个endpoint位于(i, ai)和(i,0)。找到两条线,它们与x轴一起构成一个容器,使得容器中包含最多的水。 请注意,容器不能倾斜。