LeetCode11—盛最多水的容器——双指针的妙用

一、题目描述

原题连接:https://leetcode.cn/problems/container-with-most-water/

题目描述:

给定一个长度为 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。
示例 2:

输入:height = [1,1]
输出:1

二、解题

c语言获得最小值和最大值的方法:

  1. 用三目操作符a<=b?a;b或者a>b?a:b;
  2. 也可以利用宏#define Max(a,b) a>b?a:b;   #define Min(a,b) a<=b?a:b;这样方便一点
  3. 最方便的当然还是直接调用库函数fmin,fmax函数啦!

方法1:暴力两层for循环

思路分析:定义左右边界left和right,都初始化为0,然后就是和冒泡排序的思路一样,将所有可能取值都遍历一边,遍历的同时不断更新面积最大值。

由于冒泡排序大家都很熟悉啦,这里就不赘述了,直接上代码。而且这种暴力解法会超时,也不符合堂堂中等题的解法。

int maxArea1(int* height, int heightSize) {
	assert(height);
	int i = 0;
	int j = 0;
	int max_area = 0; // 保存最大的容器容量
	for (i = 0; i < heightSize - 1; i++) {
		for (j = i + 1; j < heightSize; j++) {
			int short_plank = 0; // 每次枚举到的容器的短板
			int area = 0; // 每次枚举到的容器的容量
			short_plank = height[i] < height[j] ? height[i] : height[j];
			area = short_plank * (j - i);
			if (area > max_area) {
				max_area = area;
			}
		}
	}
	return max_area;
}

时间复杂度:O(N^2)

空间复杂度:O(1)

方法2:经典双指针

思路分析:这道题的解决方法又是经典的双指针。我们定义left和right指向数组的两端,首先我们要明确面积等于长乘高(S=LxH),H是fmin(heigh[left],heigh[right]),L是right-left。

而我们在找面积的最大值的过程中,长肯定是减小的,所以希望就寄托在高上了。

为了让高越来越高,我们每次更新左右边界的过程中就要抛弃较小的那个边,这样高就会越来越高啦,面积也就会越来越大了,直到left=right的时候,返回最大的面积即可。

有了思路,代码写起来就行云流水啦!

代码实现

int maxArea(int* height, int heightSize){
    int left=0,right=heightSize-1,max=0;
    while(left<right)
    {
        //获得本次面积
        int area = fmin(height[left], height[right]) * (right - left)
        //更新最大面积
        area=  area> max ? area : max;
        //左边边界较小,移动左边. 右边界较小,移动右边
       if(height[left] < height[right]) left++;
        else right--;
    }
       
    return max;
}

时间复杂度:O(N)

空间复杂度:O(1)

三、总结

本题又是一道很经典的双指针问题,不过是从两端开始的双指针,也是很常见的,希望大家能有所收获。

再你感觉已经完全了解双指针的时候,不妨再来道题练练手,检验检验?

977. 有序数组的平方 - 力扣(LeetCode)

此题和本题做法很相像,希望大家可以举一反三,毕竟只有自己敲出来的才是自己的!

本次刷题分享到此结束,希望大家多多点赞浏览支持啦!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值