LeetCode 42. Trapping Rain Water 【兩種解法】(python排序遍歷,C++ STL map存索引,時間複雜度O(nlogn))

LeetCode 42. Trapping Rain Water

Python解法

解題思路:

本思路需找到最高點左右遍歷,時間複雜度O(nlogn),如下爲向左遍歷的過程。python

  1. 將每個點的高度和索引存成一個元組 (val, idx)
  2. 找到最高的點(可能有多個,任取一個),記爲 (now_val, now_idx)。
  3. 向左找第一個val不大於now_val的點(left_val, left_idx)。
  4. 以left_val做爲水平面,用height[left_val+1, now_val-1]中每個點更新ans。
  5. now_val, now_idx = left_val, left_idx。
  6. 若是now_idx >= 0 ,重複執行3;不然執行7。
  7. 同理從最高點向右遍歷更新ans。

向左找的具體操做

  1. 將每個點的高度和索引存成一個元組 (val, idx)
  2. 將元組按val從大到小排序,若val相等,按idx從大到小排序。實現過程:直接sort,而後reverse。
  3. 從左向右遍歷,找到第一個idx小於now_idx的節點(left_val, left_idx),用height[left+1, now-1]中的點更新ans。
  4. 更新now節點爲left節點。
  5. 若是now_idx >= 0 ,重複執行3;不然結束循環,開始向右找。

向右找的具體操做

  1. 將每個點的高度和索引存成一個元組 (val, idx)
  2. 將元組按val從大到小排序,若val相等,按idx從小到大排序。實現過程:用functools中的cmp_to_key重載排序過程。
  3. 從左向右遍歷,找到第一個idx大於now_idx的節點(right_val, right_idx),用height[now+1, right-1]中的點更新ans。
  4. 更新now節點爲lright節點。
  5. 若是now_idx >= 0 ,重複執行3;不然執行6。
  6. 輸出ans。
注意:向左向右只有排序不一樣,其餘操做相似,

利用functools中的cmp_to_key重載排序過程代碼以下:

def mcmp(a, b):
    val1,idx1 = a
    val2,idx2 = b
    if val1 == val2:
        return idx2-idx1
    return val1-val2

from functools import cmp_to_key
l = [] # l中存元組(val, idx)
l.sort(reverse=True, key=cmp_to_key(Solution.mcmp))

代碼以下app

class Solution:
    # 利用functools中的cmp_to_key重載排序:
    def mcmp(a, b):
        val1,idx1 = a
        val2,idx2 = b
        if val1 == val2:
            return idx2-idx1
        return val1-val2
    
    def trap(self, height: List[int]) -> int:
        if len(height) == 0:
            return 0
        from functools import cmp_to_key
        l = []
        # 將(val, idx)存入l = []中
        for i in range(0, len(height)):
            l.append((height[i],i))
        
        ans = 0
        
        # 往左找
        l.sort(reverse=True)
        h, con = l[0]
        for i in range(1, len(l)):
            val, left = l[i]
            if left < con:
                for j in range(left+1, con):
                    ans += val - height[j]
                con = left
        
        # 往右找
        h, con = l[0]
        l.sort(reverse=True, key=cmp_to_key(Solution.mcmp))
        for i in range(1, len(l)):
            val, right = l[i]
            if right > con:
                for j in range(con+1, right):
                    ans += val - height[j]
                con = right
        return ans

C++解法

解題思路:

本思路與Python相似,需找到最高點左右遍歷,時間複雜度O(nlogn)如下爲向左遍歷的過程。差異在於C++是存map,無須手動排序。code

// m中first存高度val,second存索引集合。
// set<int> s = m[2]表示高度爲2的點的位置集合。
map<int, set<int>> m;

實現代碼以下:排序

class Solution {
public:
    int trap(vector<int>& height) {
        if(height.size() == 0) return 0;
        int ans = 0;
        // m中first存高度val,second存索引集合。
        // set<int> s = m[2]表示高度爲2的點的位置集合。
        map<int, set<int>> m;
        // itm表示m的一個迭代器
        map<int, set<int>>::iterator itm;
        set<int> s;
        set<int>::iterator its;
        //將(val, idx)存入map
        int sz = height.size();
        for(int i = 0;i < sz; ++i){
            m[height[i]].insert(i);
        }
        
        //向左找
        itm = --m.end();
        s = itm->second;
        int h = itm->first;
        int left = *s.begin();
        //每次找val小,idx小的
        while(left != -1 && left >= 0){
            s = m[h];
            its = s.lower_bound(left);
            if(its == s.begin()){
                if(itm == m.begin()){
                    left = -1;
                }else{
                    --itm;
                    h = itm->first;
                }
            }else{
                --its;
                for(int i = *its+1;i < left; ++i){
                    ans += h-height[i];
                }
                left = *its;
                continue;
            }
        }
        
        
        //向右找
        itm = --m.end();
        s = itm->second;
        h = itm->first;
        int right = *s.begin();
        //每次找val小,idx大的
        while(right != -1 && right < sz){
            s = m[h];
            its = s.upper_bound(right);
            if(its == s.end()){
                if(itm == m.begin()){
                    right = -1;
                }else{
                    --itm;
                    h = itm->first;
                }
            }else{
                for(int i = right+1;i < *its; ++i){
                    ans += h-height[i];
                }
                right = *its;
                continue;
            }
        }
        return ans;
    }
};
相關文章
相關標籤/搜索