131. Building Outline

本文介绍了一种使用最大堆和最小堆来减少排序消耗的方法,从而高效地找出一组建筑物的外轮廓线。通过灵活拆分和比较建筑数据,该算法能够处理复杂的重叠情况。

画建筑轮廓

LintCode链接

题目描述

水平面上有 N 座大楼,每座大楼都是矩阵的形状,可以用一个三元组表示 (start, end, height),分别代表其在x轴上的起点,终点和高度。大楼之间从远处看可能会重叠,求出 N 座大楼的外轮廓线。
外轮廓线的表示方法为若干三元组,每个三元组包含三个数字 (start, end, height),代表这段轮廓的起始位置,终止位置和高度。
参考下面的图,黑色线为建筑,红色线即为建筑的轮廓线

样例
对于下面三个链表,输出-1->2->4->null
[
  2->4->null,
  null,
  -1->null
],

思路

  1. 首先肯定能想到的是需要对输入的所有数据进行排序,排序规则应该也很好想:
    • 如果start相等,height相等,则end大的在前面
    • 如果start相等,则height大的在前面
    • start小的在前面
  2. 考虑到以下两种情况
    • [1,5,3],[2,3,5],这种情况下,需要输出[1,2,3], [2,3,5], [3,5,3]
    • [1,5,5],[2,6,3], 这种情况下,需要输出[1.5,5], [5,6,3]
  3. 考虑情景2中的两种情况,我们需要在比较过程中把建筑灵活的进行拆分,然后重新加入到待比较的数组中,再进行排序,每次排序肯定不现实,所以用到了最大最小堆来减少排序带来的消耗

代码

class Solution {
public:
    /*
    * @param buildings: A list of lists of integers
    * @return: Find the outline of those buildings
    */
    vector<vector<int>> buildingOutline(vector<vector<int>> &buildings) {
        // write your code here

        vector<vector<int>> ret;

        if (buildings.empty())
        {
            return ret;
        }

        auto func = [](vector<int> &left, vector<int> &right) {
            if (left[0] == right[0] && left[2] == right[2])
            {
                return left[1] < right[1];
            }

            if (left[0] == right[0])
            {
                return left[2] < right[2];
            }

            return left[0] > right[0];
        };
        // 建堆;
        make_heap(buildings.begin(), buildings.end(), func);

        pop_heap(buildings.begin(), buildings.end(), func);
        vector<int> cur_outline = *buildings.rbegin();
        buildings.pop_back();

        while (buildings.empty() == false)
        {
            pop_heap(buildings.begin(), buildings.end(), func);
            vector<int> building = *buildings.rbegin();
            buildings.pop_back();

            if (building[0] > cur_outline[1])
            {
                // 建筑与当前轮廓分离;
                ret.push_back(cur_outline);
                cur_outline = building;
            }
            else if (building[2] > cur_outline[2])
            {
                // 建筑与当前轮廓未分离,并且高度比当前高;
                if (building[1] < cur_outline[1])
                {
                    // 该建筑没有当前轮廓宽,生成新的建筑;
                    vector<int> new_building = { building[1], cur_outline[1], cur_outline[2] };
                    buildings.push_back(new_building);
                    push_heap(buildings.begin(), buildings.end(), func);
                }

                cur_outline[1] = building[0];
                ret.push_back(cur_outline);
                cur_outline = building;
            }
            else if (building[2] == cur_outline[2])
            {
                // 建筑与当前轮廓未分离,并且高度相等,则看是否合并轮廓;
                cur_outline[1] = max(cur_outline[1], building[1]);
            }
            else if (building[2] < cur_outline[2])
            {
                // 建筑与当前轮廓未分离,并且高度比当前小;
                if (building[0] == cur_outline[1])
                {
                    // 正好在边缘;
                    ret.push_back(cur_outline);
                    cur_outline = building;
                }
                else if (building[1] > cur_outline[1])
                {
                    // 有重叠,并且该建筑比当前轮廓宽,生成新的建筑;
                    vector<int> new_building = { cur_outline[1], building[1], building[2] };
                    buildings.push_back(new_building);
                    push_heap(buildings.begin(), buildings.end(), func);
                }
            }
        }

        ret.push_back(cur_outline);
        return ret;
    }
};
附上我的测试代码
void printfOutline(vector<vector<int>> &outline)
{
    cout << "[" << endl;
    for (auto &i : outline)
    {
        cout << "\t[";
        for (auto j : i)
        {
            cout << j << ",";
        }
        cout << "]" << endl;
    }
    cout << "]" << endl;
}

int main()
{
    Solution s;
    {
        vector<vector<int>> input = { {1, 3, 3}, { 2, 4, 4 }, { 5, 6, 1} };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,3,3}
        vector<vector<int>> input = { { 1, 3, 3 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,3,5}
        vector<vector<int>> input = { { 1, 3, 3 }, {1,3,5} };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,3,5}, {3,4,3}
        vector<vector<int>> input = { { 1, 4, 3 },{ 1,3,5 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,2,3}, {2,3,5}, {3,4,3}
        vector<vector<int>> input = { { 1, 4, 3 },{ 2,3,5 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,5,5}
        vector<vector<int>> input = { { 1, 4, 5 },{ 4,5,5 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,4,5}
        vector<vector<int>> input = { { 1, 4, 5 },{ 2,3,3 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,2,3},{2,5,5}
        vector<vector<int>> input = { { 1, 4, 3 },{ 2,5,5 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,5,3}
        vector<vector<int>> input = { { 1, 4, 3 },{ 2,5,3 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,4,5},{4,5,3}
        vector<vector<int>> input = { { 1, 4, 5 },{ 2,5,3 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,4,3}
        vector<vector<int>> input = { { 1, 4, 3 },{ 1,3,3 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    {
        // {1,4,3}
        vector<vector<int>> input = { { 1, 4, 3 },{ 1,4,3 } };
        vector<vector<int>> out = s.buildingOutline(input);
        printfOutline(out);
    }

    while (1);
}
### Outline 知识库使用指南及相关资源 Outline 是一种高效的开源知识管理工具,支持团队协作和信息共享。它不仅提供了友好的界面用于创建、编辑和分类文档,还通过其 API 接口实现了更深层次的功能扩展[^1]。 #### 官方文档与基础设置 Outline 的官方文档是获取基础知识的最佳起点。可以通过访问 [Outline官方网站](https://www.getoutline.com) 获取详细的安装说明、配置选项以及基本操作指导[^3]。这些内容涵盖了从零开始搭建 Outline 实例的过程,适合初学者快速上手。 #### 高级功能:API 和 LangChain 整合 如果希望利用 Outline 提供的高级功能,则可以参考其 API 文档。该 API 支持多种请求方式,允许开发者提取存储于 Outline 中的数据,并与其他系统集成。例如,在文章中提到过的一个案例就是将 Outline 与 LangChain 结合起来构建智能检索器[^4]。这种组合使得用户不仅可以轻松存取已有数据,还能借助自然语言处理技术实现更加精准的知识查询。 以下是基于 Python 调用 Outline API 的简单示例代码: ```python import requests def fetch_documents(api_key, collection_id): url = f"https://your-outline-instance/api/collections/{collection_id}/documents" headers = {"Authorization": f"Bearer {api_key}"} response = requests.get(url, headers=headers) if response.status_code == 200: return response.json() else: raise Exception(f"Failed to retrieve documents: {response.text}") # 替换为实际使用的 api key 和 collection id api_key = 'YOUR_API_KEY' collection_id = 'COLLECTION_ID' try: docs = fetch_documents(api_key, collection_id) print(docs) except Exception as e: print(e) ``` 此脚本展示了如何通过 RESTful API 访问特定集合下的所有文档列表[^2]。 #### 学习路径建议 对于想要深入了解 Outline 功能及其潜在应用场景的人士来说,除了阅读上述提及的文章外,还可以查阅更多关于 **Retriever** 技术的相关资料。此外,“Building Intelligent Applications with LLMs” 这本书籍也值得推荐给那些对大型语言模型感兴趣的朋友。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值