218. The Skyline Problem && 241. Different Ways to Add Parentheses

218. The Skyline Problem

A city’s skyline is the outer contour of the silhouette formed by all the buildings in that city when viewed from a distance. Now suppose you are given the locations and height of all the buildings as shown on a cityscape photo (Figure A), write a program to output the skyline formed by these buildings collectively (Figure B).

The geometric information of each building is represented by a triplet of integers [Li, Ri, Hi], where Li and Ri are the x coordinates of the left and right edge of the ith building, respectively, and Hi is its height. It is guaranteed that 0 ≤ Li, Ri ≤ INT_MAX, 0 < Hi ≤ INT_MAX, and Ri - Li > 0. You may assume all buildings are perfect rectangles grounded on an absolutely flat surface at height 0.

For instance, the dimensions of all buildings in Figure A are recorded as: [ [2 9 10], [3 7 15], [5 12 12], [15 20 10], [19 24 8] ].

The output is a list of “key points” (red dots in Figure B) in the format of [ [x1,y1], [x2, y2], [x3, y3], ... ] that uniquely defines a skyline. A key point is the left endpoint of a horizontal line segment. Note that the last key point, where the rightmost building ends, is merely used to mark the termination of the skyline, and always has zero height. Also, the ground in between any two adjacent buildings should be considered part of the skyline contour.

For instance, the skyline in Figure B should be represented as:[ [2 10], [3 15], [7 12], [12 0], [15 10], [20 8], [24, 0] ].

Notes:

  • The number of buildings in any input list is guaranteed to be in the range [0, 10000].
  • The input list is already sorted in ascending order by the left x position Li.
  • The output list must be sorted by the x position.
  • There must be no consecutive horizontal lines of equal height in the output skyline. For instance, [...[2 3], [4 5], [7 5], [11 5], [12 7]...] is not acceptable; the three lines of height 5 should be merged into one in the final output as such: [...[2 3], [4 5], [12 7], ...]
解题思路

根据题意和示例可以注意到,轮廓中每个点的横坐标恰好是建筑物的左右顶点的横坐标,所以应该要先对这些顶点进行排序,然后从左往右遍历(同样有下面的规律):

  • 如果是左顶点,并且是当前最高点,则应该把该点加入结果中;

  • 如果是右顶点,并且是当前最高点,则应该加入一个新的点,这个点由这个点的横坐标去掉该点后最高点的纵坐标组成。(也即,若与其他建筑相交,该点则为所求交点,否则该点为与地面的交点)

具体的实现中,使用红黑树(multiset)存储各点的高度,方便找最大值与插入、删除

程序代码
class Solution {
public:
    vector<pair<int, int>> getSkyline(vector<vector<int>>& buildings) {
        vector<pair<int, int>> h, res;
        //把所有左右顶点进行排序
        for (auto building: buildings){
            h.push_back({building[0], -building[2]}); 
            h.push_back({building[1], building[2]});
        }
        sort(h.begin(), h.end());
        //从左往右对各顶点遍历:
        //    若为左顶点,且为最高点,则加入该点坐标;
        //    若为右顶点,且为最高点,则加入新坐标,该坐标为该点的横坐标与除去该点后的最高点的纵坐标。
        //使用红黑树(multiset)对高度进行排序
        multiset<int> heights;
        int pre = 0, cur = 0;
        heights.insert(0);
        for (auto node: h){
            if (node.second < 0) heights.insert(-node.second);
            else heights.erase(heights.find(node.second));
            cur = *(heights.rbegin()); //最高点的高度
            if (pre != cur){
                res.push_back({node.first, cur});
                pre = cur;
            }
        }
        return res;
    }
};

241. Different Ways to Add Parentheses

Given a string of numbers and operators, return all possible results from computing all the different possible ways to group numbers and operators. The valid operators are +, - and *.

Example 1:

Input: "2-1-1"
Output: [0, 2]
Explanation: 
((2-1)-1) = 0 
(2-(1-1)) = 2

Example 2:

Input: "2*3-4*5"
Output: [-34, -14, -10, -10, 10]
Explanation: 
(2*(3-(4*5))) = -34 
((2*3)-(4*5)) = -14 
((2*(3-4))*5) = -10 
(2*((3-4)*5)) = -10 
(((2*3)-4)*5) = 10
解题思路

一开始很自然地想要遍历所有运算符,作为第一步,然后逐渐缩小式子,得到结果。但是这样会出现重复的情况,想了很久不知道怎么去掉重复的情况。

之后参考StefanPochmann的解法,非常优雅的python跟C++代码。

主要思路也是遍历所有运算符,但是把这一运算符作为最后一步;如此,只要最后一步不同,就可保证不会有重复的情况,具体地看代码,非常简洁清晰。

程序代码
#include <sstream>
class Solution {
public:
    vector<int> diffWaysToCompute(string input) {
        vector<int> res;
        //遍历所有运算符
        for (int i = 0; i < input.size(); i++){
            char c = input[i];  
            if (c == '+' || c == '-' || c == '*'){
                //以该运算符为最后一步运算
                for (int a: diffWaysToCompute(input.substr(0, i)))
                    for (int b: diffWaysToCompute(input.substr(i + 1)))
                        res.push_back(c == '+'? a + b: c == '-'? a - b: a * b);
            }
        }
        return res.size()? res: vector<int>{stoi(input)};
    }
};

猜你喜欢

转载自blog.csdn.net/qq_36153312/article/details/81951615