雨水容量
Problem statement:
问题陈述:
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining?
给定n个表示海拔图的非负整数,其中每个条的宽度为1,计算下雨后它能捕集多少水?
Input:
输入:
The first line of input contains an integer T denoting the number of test cases. The first line of each test case is N, N is the size of the array. The second line of each test case contains N input arr[i], where arr[i] represent the height of the building.
输入的第一行包含一个整数T,表示测试用例的数量。 每个测试用例的第一行是N , N是数组的大小。 每个测试用例的第二行包含N个输入arr [i] ,其中arr [i]代表建筑物的高度。
Output:
输出:
For each testcase, print the maximum water stored in those building.
对于每个测试用例,请打印存储在这些建筑物中的最大水量。
Examples:
例子:
Input:
T = 1
N = 6
[6,2,4,2,4,6]
Output:
12, 4, units of water at index 1 and 3 and 2 unit
of water at index 2 and 4, hence overall 12 units of water.
Input:
T = 1
N = 3
[4,4,4,4,4]
Output:
0,
We cannot store any amount of water in
this construction as all are equal.
Solution Approach
解决方法
1) Brute Force Approach
1)蛮力法
The idea is to traverse every array element and find the highest bars on the left and right sides. Take the smaller of two heights. The difference between the smaller height and height of the current element is the amount of water that can be stored in this array element.
想法是遍历每个数组元素,并在左侧和右侧找到最高的条形。 取两个高度中的较小者。 当前元素的较小高度和高度之间的差是可以存储在此数组元素中的水量。
We will traverse the array from start to end, for every element we will find the maximum value from left and right and then take the minimum value and subtract that from the current height of the building. We will keep summing the values from first to last.
我们将从头到尾遍历该数组,对于每个元素,我们将从左和右找到最大值,然后取最小值并将其从建筑物的当前高度中减去。 我们将始终从头到尾求和。
Pseudo Code:
伪代码:
maxwater(int arr[],int n):
for (int i = 1; i < n-1; i++){
// Find the maximum element on its
// left and keep it on left vaiable.
int left = arr[i]
for (int j=0; j<i; j++)
left = max(left, arr[j]);
// Find the maximum element on its
// right and keep it on right variable.
int right = arr[i];
for (int j=i+1; j<n; j++)
right = max(right, arr[j]);
// keep updating values in res variable.
res = res + (min(left, right) - arr[i]);
}
Time Complexity for above approach: O(n*n)
上述方法的时间复杂度: O(n * n)
space Complexity for above approach: O(1)
上述方法的空间复杂度: O(1)
C++ Implementation:
C ++实现:
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t;
cout << "Enter number of test cases: ";
cin >> t;
while (t--) {
int n;
cout << "Enter size of array: ";
cin >> n;
cout << "Enter number of elements: ";
int arr[n];
for (int i = 0; i < n; i++)
cin >> arr[i];
int sum = 0;
for (int i = 1; i < n - 1; i++) {
//initialise left temporary variable.
int left = arr[i];
//initialise right temporary variable.
int right = arr[i];
for (int j = 0; j < i; j++)
left = max(arr[j], left); //find left maximum values.
//int right=arr[i];
for (int j = i + 1; j < n; j++)
right = max(right, arr[j]); //find right maximum values.
//take the amount of water it can hold and take summation.
sum += (min(left, right) - arr[i]);
}
cout << sum << "\n";
}
return 0;
}
Output
输出量
Enter number of test cases: 3
Enter size of array: 5
Enter number of elements: 4 5 6 2 3
1
Enter size of array: 6
Enter number of elements: 6 2 4 2 4 6
12
Enter size of array: 4
Enter number of elements: 1 2 3 4
0
2) Efficient Approach
2)有效的方法
We will use precomputed values of height in two arrays left and right.
我们将在左右两个数组中使用预先计算的高度值。
Initially left[0] value will be same as left[0]=arr[0] as there are no other element left of it and right[n-1] will be arr[n-1] as there is no other right element. For other elements we will take min(left[i],right[i])-arr[i] as the sum of water.
最初的left [0]值将与left [0] = arr [0]相同,因为它的左边没有其他元素,而right [n-1]将是arr [n-1],因为没有其他右边的元素。 对于其他元素,我们将min(left [i],right [i])-arr [i]作为水的总和。
Pseudo Code:
伪代码:
maxwater(int arr[],int n):
//left and right array declaration.
left[n],right[n]
//left[0]=arr[0] as there are no elements to left of it.
left[0]=arr[0]
//right[n-1] =arr[n-1] as there is no elements.
right[n-1]=arr[n-1]
for(int i=1;i<n;i++)
//iterate each element from index 1 to n-1 and
//keep checking left of it for maximum values.
left[i]=max(left[i-1],arr[i])
for(int j=n-2;j>=0;j--)
//iterate each element from index n-2 to 0 and
//keep checking right of it for maximum values.
right[i]=max(right[i+1],arr[i])
for(int i=0;i<n;i++)
//keep summation of the maximum water values.
sum+=((left[i]-right[i])-arr[i])
return sum
Time Complexity for above approach: O(n)
上述方法的时间复杂度: O(n)
Space Complexity for above approach: O(n)
上述方法的空间复杂度: O(n)
C++ Implementation:
C ++实现:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
ll t;
cout << "Enter number of test cases: ";
cin >> t;
while (t--) {
ll n;
cout << "Enter size of array: ";
cin >> n;
ll arr[n];
cout << "Enter array elements: ";
for (ll i = 0; i < n; i++)
cin >> arr[i];
//declare array elements left and right.
ll left[n], right[n];
left[0] = arr[0];
right[n - 1] = arr[n - 1];
for (int i = 1; i < n; i++) {
//take max of left values.
left[i] = max(left[i - 1], arr[i]);
}
for (int i = n - 2; i >= 0; i--)
//take max of right values.
right[i] = max(right[i + 1], arr[i]);
ll sum = 0;
for (ll i = 1; i < n - 1; i++) {
//take summation of maximum water amount of water.
sum += (min(left[i], right[i]) - arr[i]);
}
//print maximum amount of water.
cout << sum << "\n";
}
return 0;
}
Output
输出量
Enter number of test cases: 3
Enter size of array: 5
Enter array elements: 1 2 3 4 5
0
Enter size of array: 5
Enter array elements: 5 4 3 2 1
0
Enter size of array: 6
Enter array elements: 9 2 5 2 4 1
5
Problem reference: https://leetcode.com/problems/trapping-rain-water/
问题参考: https : //leetcode.com/problems/trapping-rain-water/
翻译自: https://www.includehelp.com/icp/rain-water-trapping-problem.aspx
雨水容量