给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。
说明:你不能倾斜容器,且 n 的值至少为 2。
图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。
示例:
输入: [1,8,6,2,5,4,8,3,7]
输出: 49
双指针(对撞指针)类型问题,面积为短的一侧*距离,则面积最终取决于短的一边,因此指针移动也是移动短的一根
class Solution {
function maxArea($height) {
//对撞指针
$max = 0;
for($i = 0,$j = count($height)-1;$i<$j;){
//优先左侧移动
if($height[$i]<=$height[$j]){
$area = ($j-$i)*$height[$i];
$i++;
}else{
$area = ($j-$i)*$height[$j];
$j--;
}
$max = max($max,$area);
}
return $max;
}
}
在未排序的数组中找到第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入:
[3,2,1,5,6,4] 和
k = 2
输出: 5示例 2:
输入:
[3,2,3,1,2,4,5,5,6] 和
k = 4输出: 4
利用快排的思想,快排也利用了双指针,每次执行partition函数都会把结果逼向接近答案的一方
class Solution {
function findKthLargest($nums, $k) {
//对撞指针
$aim = count($nums)-$k;//从小到大排序,第k大即为总数减去排位k
$low = 0;
$height = count($nums)-1;
$position = $this->partition($nums,$low,$height);
//将结果逼近到目标答案处
while ($position != $aim) {
if($position > $aim){
$height = $position-1;
}else{
$low = $position+1;
}
$position = $this->partition($nums,$low,$height);
}
return $nums[$position];
}
//快排关键函数,分区函数
function partition(&$arr,$low,$height){
$flag = $arr[$low];
while ($low<$height) {
while ($low<$height && $arr[$height] >= $flag) {
$height--;
}
$this->swap($arr,$low,$height);
while ($low<$height && $arr[$low] < $flag) {
$low++;
}
$this->swap($arr,$low,$height);
}
return $low;
}
//交换函数
function swap(&$arr,$i,$j){
$tmp = $arr[$i];
$arr[$i] = $arr[$j];
$arr[$j] = $tmp;
}
}
双指针问题在LeetCode中还有很多,如75,88,167,125,344,345