1. 程式人生 > >Leetcode:391.完美矩形

Leetcode:391.完美矩形

我們有 N 個與座標軸對齊的矩形, 其中 N > 0, 判斷它們是否能精確地覆蓋一個矩形區域。

每個矩形用左下角的點和右上角的點的座標來表示。例如, 一個單位正方形可以表示為 [1,1,2,2]。 ( 左下角的點的座標為 (1, 1) 以及右上角的點的座標為 (2, 2) )。

示例 1:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [3,2,4,4],
  [1,3,2,4],
  [2,3,3,4]
]

返回 true。5個矩形一起可以精確地覆蓋一個矩形區域。

 

示例 2:

rectangles = [
  [1,1,2,3],
  [1,3,2,4],
  [3,1,4,2],
  [3,2,4,4]
]

返回 false。兩個矩形之間有間隔,無法覆蓋成一個矩形。

 

示例 3:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [3,2,4,4]
]

返回 false。圖形頂端留有間隔,無法覆蓋成一個矩形。

 

示例 4:

rectangles = [
  [1,1,3,3],
  [3,1,4,2],
  [1,3,2,4],
  [2,2,4,4]
]

返回 false。因為中間有相交區域,雖然形成了矩形,但不是精確覆蓋。

解題思路:

邏輯題,數學題,雜湊。如果明白完美矩形的數學描述以及非常規型別的雜湊實現,那麼這題就easy了。

完美矩形的數學描述:假設最終的區域裡,s所有頂點的x_min,x_max,y_min,y_max被唯一確定,所有小的矩形的面積總和face。滿足完美矩形需要3個條件。

  1. (x_max - x_min)*(y_max - y_min) == face。
  2. 4個頂點只出現過一次。
  3. 其餘頂點必然出現過偶數次。(1次和3次都會出現空缺,代表不完美)

另外,判斷某個頂點是否出現,需要用非常規型別的雜湊實現。這個非常規型別是兩個int。通過字串流,可以將int轉成字串,然後將多個int轉成的字串相連,中間加入空格,組成的一個大字串,就是我們最終要查詢的物件。

stringstream ss;

ss<<int;

ss>>string; 

這樣一來,別說兩個int,多個int也是可以的。另外字串流還可以轉換其他型別,不僅僅是int,因此方法比較通用。我也看見過官方給出的運算速度最快的程式碼,方法基本類似,就是把兩個int連結成了long long,效率更高,但是不能解決一般的非常規資料型別的hash, 因此各有各的好處。

int  a=123454,b=4345==>string res="123454 4345".

C++程式碼

class Solution {
public:
    
    bool isRectangleCover(vector<vector<int>>& rectangles) {
        int size = rectangles.size();
        int x_max = INT_MIN, x_min = INT_MAX, y_max = INT_MIN, y_min = INT_MAX;
        int face=0;
        stringstream ss;
        string x_str, y_str;
        unordered_map<string, int> mp;
        for (int i = 1; i <= size; i++) {
            int dx, dy;
            dx = abs(rectangles[i - 1][2] - rectangles[i - 1][0]);
            dy = abs(rectangles[i - 1][3] - rectangles[i - 1][1]);
            face += dx*dy;
            x_max = max(x_max, rectangles[i - 1][2]);
            x_max = max(x_max, rectangles[i - 1][0]);
            x_min = min(x_min, rectangles[i - 1][2]);
            x_min = min(x_min, rectangles[i - 1][0]);
            y_max = max(y_max, rectangles[i - 1][3]);
            y_max = max(y_max, rectangles[i - 1][1]);
            y_min = min(y_min, rectangles[i - 1][3]);
            y_min = min(y_min, rectangles[i - 1][1]);
            ss.clear();
            ss << rectangles[i - 1][0] << " " << rectangles[i - 1][1];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
            ss.clear();
            ss << rectangles[i - 1][2] << " " << rectangles[i - 1][3];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
            ss.clear();
            ss << rectangles[i - 1][0] << " " << rectangles[i - 1][3];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
            ss.clear();
            ss << rectangles[i - 1][2] << " " << rectangles[i - 1][1];
            ss >> x_str >> y_str;
            mp[x_str + " " + y_str]++;
        }
        if ((y_max - y_min)*(x_max - x_min) != face) return false;
        //4個頂點對應的字串
        
        string UL, UR, DL, DR;
        ss.clear();
        ss << x_min << " " << y_max;
        ss >> x_str >> y_str;
        UL = x_str +" "+ y_str;
        ss.clear();
        ss << x_max << " " << y_max;
        ss >> x_str >> y_str;
        UR = x_str + " " + y_str;
        ss.clear();
        ss << x_min << " " << y_min;
        ss >> x_str >> y_str;
        DL = x_str + " " + y_str;
        ss.clear();
        ss << x_max << " " << y_min;
        ss >> x_str >> y_str;
        DR = x_str + " " + y_str;

        if (mp[UL] != 1 || mp[UR] != 1 || mp[DL] != 1 || mp[DR] != 1) {
            return false;
        }
        unordered_map<string, int>::iterator it;
        for (it = mp.begin(); it != mp.end(); it++) {
            if (it->second % 2 == 1) {
                if (!(it->first == UL || it->first == UR || it->first == DL || it->first == DR)) {
                    return false;
                }
            }
        }
        return true;
    }
};