inttrap(vector<int>& height){ int n = height.size(); int res = 0; for (int i = 1; i < n; ++i) {
//往左找到最大值 int lmax = 0; for (int j = 0; j < i; ++j) { lmax = max(lmax, height[j]); }
//往右找到最大值 int rmax = 0; for (int j = i + 1; j < i; ++j) { rmax = max(rmax, height[j]); }
res += min(rmax, lmax) - height[i];
} }
时间复杂度:$O(n^2)$ 空间复杂度:$O(1)$
接雨水问题-进一步思考
观察上面的代码,有很多重复计算,例如计算i左边的最大值时,扫描范围是[0, i - 1];当计算i+1左边的最大值时,扫描范围是[0, i],显然是完全包含[0, i - 1]的, 对于重复计算,我们继续采用空间换时间的套路,用数组lmax[i]来存储[0, i - 1]的最大值;这样子存储之后,如果再计算lmax[i + 1]只要拿lmax[i]跟height[i + 1]比较即可。
接雨水问题-空间换时间版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
inttrap(vector<int>& height){ int n = height.size(); int res = 0; int lmax[N], rmax[N]; //正序遍历 for (int i = 1; i < n; ++i) { lmax[i] = max(lmax[i - 1], height[i - 1]); }
//倒序遍历 for (int i = n; i >= 0; --i) { rmax[i] = max(rmax[i + 1], height[i + 1]); }
for (int i = 1; i < n; ++i) { res += min(lmax[i], rmax[i]) - height[i]; } }
classSolution { public: /** * max water * @param arr int整型vector the array * @return long长整型 */ longlongmaxWater(vector<int>& arr){ stack<int> s; s.push(-1); int res = 0; for (int i = 0; i < arr.size(); ++i) { while (s.top() != -1 && arr[s.top()] < arr[i]) { int cur = s.top(); //当前计算的格子 s.pop(); int left = s.top(); if (left >= 0) { res += (min(arr[left], arr[i]) - arr[cur]) * (i - left - 1); //cout << "i:" << i << ", cur:" << cur << ", res: " << res << endl; } }