有意思的數學題:Trapping Rain Water

LeetCode傳送門 https://leetcode.com/problems/trapping-rain-water/ios

 

 

目標:找出積木能容納的水的「面積」,如圖中黑色部分是積木,藍色爲可容納水的部分git

假設:積木寬度均爲1github

輸入:各個積木的高度app

輸出:全部積木能容納水的「面積」ide

 

思考過程

1. 逐一求積木的間隔彷佛不太容易。特別對於圖中3-7積木間的容積,若是能夠先求底部(4-6間)的容積,當求解上層(3-7)的容積時,還須要作額外的處理,如減掉底部的高度。spa

2. 既然如此,能否先求出3-7間總體的容積,再將兩積木之間的積木面積(四、五、6)減去,便可得這個區域的容積?3d

3. 那麼問題轉換成了,已知一個積木,如何尋找下一個積木,並計算這個兩積木間的容積code

4. 嘗試一,尋找一個至少不比當前積木低的積木,做爲下一個積木,如圖例子爲當前積木3,下一個積木7。那麼之間的容積如何計算呢,簡單,積木3的高度乘以兩積木間的間隔寬度,再減去,積木3與積木7之間的積木(四、五、6)面積。blog

5. 問題:下次迭代從何開始?上一個例子,能夠從積木7繼續算起。然而若是找不到相應的積木呢,那麼從積木3的下一個積木4開始。leetcode

6. 看起來,彷佛正確。因而乎,開始寫代碼了。然而第一次提交就獻給了WA(/(ㄒoㄒ)/~~)

7. 錯誤的狀況,若是當前的積木是一個特別高的積木,後繼找不到更高的積木,然而實際上之間是可能有容積的!不贅述了,補救思路是:在尋找更高的積木的同時,記錄當前找到的最高的積木。若是沒有找到更高的積木,使用當前找到的最高的積木做爲下一個積木,並計算容積。

 

思路總結

迭代的過程

1. 尋找下一個至少不比當前積木低的積木,尋找的同時,記錄當前找到的最高的積木高度

2. 若是找到,則計算兩積木之間的容積(計算過程見思考過程2)

3. 若是沒有找到,則計算當前積木與當前找到的最高的積木之間的容積

4. 當前積木設置爲找到的積木(多是2或3的狀況),繼續迭代

 

時間複雜度

O(n)

 

代碼實現

 1 #include <iostream>
 2 #include <vector>
 3 
 4 using namespace std;
 5 
 6 class Solution {
 7 public:
 8     int trap(vector<int>& height) {
 9         if (height.size() == 0) {
10             return 0;
11         }
12 
13         int water = 0;
14         int preIndex = 0;
15         int preHeight = 0;
16 
17         // 找到第一個高度非0的bar
18         while (preIndex < height.size() - 1 && height[preIndex] == 0) {
19             ++preIndex;
20         }
21 
22         if (preIndex == height.size() - 1) {
23             return 0;
24         }
25 
26         // 遍歷
27         while (preIndex < height.size()) {
28             preHeight = height[preIndex];
29 
30             // 尋找更高的或相等的bar
31             // 同時記錄遍歷過的最高的bar
32             // 若是尋找不到更高的或相等的bar時,使用記錄值計算
33             int next = preIndex + 1;
34             int minHeight = 0;
35             int minIndex = next;
36 
37             while (next < height.size() && height[next] < preHeight) {
38                 if (height[next] > minHeight) {
39                     minHeight = height[next];
40                     minIndex = next;
41                 }
42                 ++next;
43             }
44 
45             // 若是找到
46             if (next != height.size()) {
47                 water += (preHeight * (next - preIndex - 1)); // 計算總面積
48 
49                 for (int i = preIndex + 1; i < next; ++i) { // 減去中間bar面積
50                     water -= height[i];
51                 }
52 
53                 preIndex = next; // 從找到的bar開始下一次的迭代
54             } else {
55                 water += (minHeight * (minIndex - preIndex - 1)); // 計算總面積
56 
57                 for (int i = preIndex + 1; i < minIndex; ++i) { // 減去中間bar面積
58                     water -= height[i];
59                 }
60 
61                 preIndex = minIndex; // 從次高的bar開始
62             }
63         }
64 
65         return water;
66     }
67 };
68 
69 int main(int argc, char const *argv[]) {
70     Solution solution;
71     vector<int> height = {0,1,0,2,1,0,1,3,2,1,2,1};
72     cout << solution.trap(height) << endl;
73     return 0;
74 }
Trapping Rain Water

 

閒聊一二

大年初一!祝你們猴年快樂啦,已經工做的童鞋升職加薪,要實習、找工做的童鞋offer多多~博主今年也要面對找實習、找工做的人生大事兒了。很久沒寫博客了,默默的哀悼上個學期,本身瞎折騰,弄出的不成熟的東西。但願猴年是激情,奮鬥,收穫的一年~

 

ps:有沒有對我感興趣的boss收留~附交友地址一枚https://github.com/zrss

簡單粗暴的resume:https://github.com/zrss/ghostblog,近期再修改下

相關文章
相關標籤/搜索