7.20 牛客左程云第2题(个人学习笔记)
来源:互联网 发布:手机淘宝卖家发货流程 编辑:程序博客网 时间:2024/06/15 08:32
题目:给定一个非负数的数组,代表一个容器。例如数组[0,1,0,2,1,0,1,3,2,1,2,1],就是以下图形中黑色的部分。如果用这个容器接水的话,请问可以接多少水?还以这个数组为例,可以接 6 格水,就是以下图形中蓝色的部分。
要求:实现时间复杂度 O(N),额外空间复杂度 O(1)的解法
解法一:常规解法
对每一个数值求左右侧最大值,然后求出对应水量,水量应为左右侧最小值减去该数值(得出的水量与0比较,取大者);一直遍历到最后一个元素,显然时间复杂度过大。
C++代码
#include<iostream>using namespace std;int max(int a,int b){return a > b ? a : b;}int min(int a, int b){return a < b ? a : b;}int getWater1(int* arr,int length) {if (arr == NULL || length < 3) return 0;int value = 0;for (int i = 1; i <length - 1; i++) {int leftMax = 0;int rightMax = 0;for (int l = 0; l < i; l++) {leftMax = max(arr[l],leftMax);}for (int r = i + 1; r <length; r++) {rightMax = max(arr[r],rightMax);}value += max(0, min(leftMax, rightMax) - arr[i]);}return value;}解法二:
采用2个辅助数组,用来存放i位置(Left)左侧最高值和(right)右侧最高值.
具体过程是,首先遍历得Left数组,然后反向遍历得Right数组;最后遍历各个位置求水量,知时间复杂度为O(n)但空间复杂度过大
C++代码
int getWater2(int*arr,int length) {if (arr == NULL || length < 3) {return 0;}int n = length - 1;int* leftMaxs = new int[n];leftMaxs[0] =0;for (int i = 1; i < n; i++) //遍历得left数组,表示该位置左侧的最大值{leftMaxs[i] = max(leftMaxs[i - 1], arr[i-1]);}int*rightMaxs = new int[n];rightMaxs[n - 1] = arr[n];for (int i = n - 2; i >= 0; i--) <span style="font-family: Arial, Helvetica, sans-serif;">//遍历得right数组,表示该位置右侧的最大值</span>{rightMaxs[i] = max(rightMaxs[i+1], arr[i + 1]);}int value = 0;for (int i = 1; i <= n-1; i++){ value += max(0,min(leftMaxs[i], rightMaxs[i]) - arr[i]);//取2侧最小值与该位置值相减得水量(还要与0作比较)}return value;}解法三:
left数组可在解法二的第3个遍历中用一个变量取代,进一步缩小空间复杂度
C++代码如下
int getWater3(int* arr,int length) {if (arr == NULL ||length < 3) {return 0;}int n = length - 1;int*rightMaxs = new int[n];rightMaxs[n - 1] = arr[n];for (int i = n - 2; i >= 0; i--){rightMaxs[i] = max(rightMaxs[i + 1], arr[i + 1]);}int leftMax = arr[0];int value = 0;for (int i = 1; i <= n-1; i++) {value += max(0, min(leftMax, rightMaxs[i]) - arr[i]);leftMax=max(leftMax, arr[i]);//此处相当于解法2的left数组}return value;}
解法四:
不用辅助数组,仅用2个变量代替left与right,符合要求
例子
5 4 6 8 2 3 7
| |
L R
(1)对于4和3 此时左侧最大值为5, 右侧最大值为7;由于4左侧最大值小于右侧,故此时4的水量可算出(想象水桶,水的多少取决于最短的木板) ,即5-4=1;
然后L++
5 4 6 8 2 3 7
| |
L R
(2)对于6,3; 左max为5,右max为7,所以6的水量同样可算出,即 5-6=-1,无水量 0,L++
5 4 6 8 2 3 7
| |
L R
(3)对于8和3;左max为6,右max为7,所以8的水量同样可算出,即 6-8=-2,无水量 0,L++5 4 6 8 2 3 7
| |
L R
(4)对于2和3;左max为8,右max为7,此时3的水量可算出,即 7-3=4 ,R--
5 4 6 8 2 3 7
| |
L R
最后一步 对于2 为7-2=5
C++代码
int getWater4(int* arr,int length) {if (arr == NULL || length < 3) {return 0;}int value = 0;int leftMax = arr[0];int rightMax = arr[length - 1];int l = 1;int r = length - 2;while (l <= r) {if (leftMax <= rightMax) {value += max(0, leftMax - arr[l]);leftMax =max(leftMax, arr[l++]);}else {value += max(0, rightMax - arr[r]);rightMax = max(rightMax, arr[r--]);}}return value;}
- 7.20 牛客左程云第2题(个人学习笔记)
- 7.20 牛客左程云老师第一题(个人学习笔记)
- 7.20 左程云牛客第3题 (个人学习笔记)
- 个人学习笔记(一)
- 学习笔记(个人记录)
- 学习个人学习XML笔记(一)
- Java IO的个人学习笔记(2)
- C 语言学习笔记 (个人)
- 学习 Box2D 个人笔记(一)b2World
- 学习 Box2D 个人笔记(二)b2body .
- 学习 Box2D 个人笔记(三)ApplyForce
- 学习 Box2D 个人笔记(四)b2MouseJoint
- 学习 Box2D 个人笔记(六)PrismaticJoint
- 学习 Box2D 个人笔记(五)debugDraw
- 学习 Box2D 个人笔记(七)b2DistanceJoint
- 学习 Box2D 个人笔记(八)b2RevoluteJoint
- 学习 Box2D 个人笔记(八)b2PulleyJoint
- 学习 Box2D 个人笔记(九)b2GearJoint
- 刚体变量
- Centos6.5安装Maven
- linux 关闭popen 打开的命令
- kmp应用
- Set
- 7.20 牛客左程云第2题(个人学习笔记)
- Android版本和API Level对应关系
- Java基础之(十四)成员变量和局部变量
- 随机变量函数的分布求法和转换思想
- JS代码优化的几种方式
- Java基础之-IO中的File类
- MVC
- linux学习之cut的用法
- LeetCode | Binary Tree Level Order Traversal I,II