刷题笔记:力扣第11题-盛最多水的容器
·


1.拿到题目,能想到的最简单的方法是两个for循环遍历,但这种时间复杂度为O(n2)的解法实在是不想再去用,于是开始思考这个题有没有什么规律。既然要找最大值,那么就应该想一想什么情况下可能最大。已知面积=短边长度*数组元素之间距离,那么可以先假定数组元素之间距离为最大值,即最左边和最右边,然后慢慢向中间靠拢,防止有特殊情况出现。初步写的代码如下:
1. int minNum(int a, int b){
2. return a < b ? a : b;
3. }
4.
5. int maxArea(int* height, int heightSize) {
6. int left = 0, right = heightSize - 1;
7. int max = 0;
8. while (left < right){
9. int length = right - left;
10. if (max < minNum(height[left], height[right]) * length){
11. max = minNum(height[left], height[right]) * length;
12. }
13. left++;
14. }
15. left = 0;
16. right = heightSize - 1;
17. while (left < right){
18. int length = right - left;
19. if (max < minNum(height[left], height[right]) * length){
20. max = minNum(height[left], height[right]) * length;
21. }
22. right--;
23. }
24. return max;
25. }
2.本地测试能通过,但提交以后出现问题了,仔细检查后发现,我目前写的方法虽然有双指针的影子,但是考虑的情况不完全。我只考虑了两种情况,最左边指针不动、最右边指针移动以及最右边指针不动、最左边指针移动的情况,但实际上最大值可能出现在数组中间。
3.咨询了ai,发现指针移动的核心思想可以是比较左右两个指针所指的数组元素的大小,小的那个进行移动来尝试找更大解。写出的代码如下:
1. // 辅助函数:返回两个数的较小值(容器的有效高度由短板决定)
2. int minNum(int a, int b){
3. return a < b ? a : b;
4. }
5.
6. int maxArea(int* height, int heightSize) {
7. // 1. 初始化双指针:左指针在最左,右指针在最右
8. int left = 0, right = heightSize - 1;
9. // 2. 初始化最大容量为0(记录遍历过程中的最大值)
10. int max = 0;
11.
12. // 3. 核心循环:左右指针未相遇时继续遍历
13. while (left < right){
14. // 3.1 计算当前容器的宽度(右指针 - 左指针)
15. int length = right - left;
16. // 3.2 计算当前容器的容量:短板高度 * 宽度
17. int currentArea = minNum(height[left], height[right]) * length;
18.
19. // 3.3 更新最大容量:如果当前容量更大,替换max
20. if (max < currentArea){
21. max = currentArea;
22. }
23.
24. // 3.4 核心:移动短指针(关键规则)
25. if (height[left] < height[right]){
26. left++; // 左指针更短,右移左指针
27. } else {
28. right--; // 右指针更短(或相等),左移右指针
29. }
30. }
31.
32. // 4. 返回最大容量
33. return max;
34. }
4.当height[left] == height[right]时为什么移动哪个指针都可以?因为当两边高度相同时,不论是移动左指针还是右指针,新的容量都不可能超过当前容量(宽度变小,短板高度最多等于当前高度),因此移动任意一个指针都不会错过最优解。
更多推荐

所有评论(0)