【问题标题】:Placing blocks and calculating height of the highest tower放置积木并计算最高塔的高度
【发布时间】:2017-08-31 05:43:47
【问题描述】:

给出了一系列 k 块 (k1, k2, ..., ki)。每个块从位置 ai 开始,到位置 bi 结束,其高度为 1。块连续放置。如果该块与另一个块重叠,则它被附加在其顶部。我的任务是计算最高的积木塔。 我创建了一个时间复杂度约为 O(n^2) 的算法,但我知道使用 skiplist 有一个更快的解决方案。

#include <iostream>

struct Brick
{
    int begin;
    int end;
    int height = 1;
};

bool DoOverlap(Brick a, Brick b)
{
    return (a.end > b.begin && a.begin < b.end)
}

int theHighest(Brick bricks[], int n)
{
    int height = 1;

    for (size_t i = 1; i < n; i++)
    {
        for (size_t j = 0; j < i; j++)
        {
            if (bricks[i].height <= bricks[j].height && DoOverlap(bricks[i], bricks[j]))
            {
                bricks[i].height = bricks[j].height + 1;

                if (bricks[i].height > height)
                    height = bricks[i].height;
            }
        } 
    }

    return height;
}

That's an example drawing of created construction.

【问题讨论】:

  • 你有什么问题?你的代码在哪里?
  • 你能分享你创建的算法吗?
  • ai , bi 的范围是多少?
  • 我添加了一个代码。 ai、bi 的范围不受限制,例如 (5,10)、(6,12)。我没有提到每个位置都是自然数,请原谅可能的误解。

标签: algorithm


【解决方案1】:

您可以在根据起始位置对块进行排序后简单地使用2个指针,如果它们的起始位置匹配,则根据它们的结束位置对它们进行排序。然后只需使用 2 个指针即可找到最大高度。

时间复杂度:O(NlogN)

您可以找到演示链接here

#include <bits/stdc++.h>
using namespace std;

#define ii pair<int,int>

bool modified_sort(const pair<int,int> &a,
              const pair<int,int> &b)
{
    if (a.first == b.first) {
        return (a.second <b.second);
    }
    return (a.first <b.first);
}
int main() {
    // your code goes here
    vector<ii> blocks;
    int n; // no of blocks
    int a,b;
    cin>>n;
    for (int i=0;i<n;i++) {
        cin>>a>>b;
        blocks.push_back(ii(a,b));
    }
    sort(blocks.begin(), blocks.end(), modified_sort);
    int start=0,end=0;
    int max_height=0;
    while(end<n) {
         while(start<end && blocks[start].second <= blocks[end].first) 
         {
            start++;
         }
         max_height = max(max_height,(end-start+1));
         end++;
    }
    cout<<max_height<<endl;
    return 0;
}

【讨论】:

    【解决方案2】:

    这是一个简单的解决方案(没有跳过列表):

    创建数组heights

    遍历块。

    对于每个区块

    • 通过迭代检查 heights 数组中的现有条目,了解当前块占据的位置。确定它们的最大值。

    • 将当前块的高度数组中的值增加到上一步中确定的最大值+1。

    • 记录您在扫描期间建造的最大塔的得分。

    【讨论】:

    • 我不确定您是否正确理解了我的意思。如果在将块放在另一个块上时确定每个块的高度,那么创建一个高度数组有什么意义?
    • 不必为每一块砖都经过所有其他砖
    • 如果可能的位置稀疏,请使用散列而不是数组。
    【解决方案3】:

    这个问题与图遍历同构。每个区间(块)是图的一个节点。两个块由一条边 iff 连接,它们的间隔重叠(堆叠的可能性)。你给出的例子有图边

    1 2
    1 3
    2 3
    2 5
    and node 4 has no edges
    

    您的最高堆栈与图中最长的无循环路径同构。这个问题有众所周知的解决方案。

    顺便说一句,我不认为你的 n^2 算法适用于所有的块排序。尝试一组六个块,每个块有一个重叠,例如 {2, 4, 6, 8, 10, 12} 中 n 的区间 [n, n+3]。将这些块的所有排列输入到您的算法中,并查看每个排列的高度是否为 6。


    复杂性

    我认为最复杂的可能是对区间进行排序以加速标记边缘。排序将是 O(n log n)。添加边是 O(n d),其中 d 是图的平均度数(n*d 是边数)。

    我并没有牢牢记住graph traversal algorithm,但我希望它是O(d log n)

    【讨论】:

    • 这真是个有趣的解决方案。那大概的时间复杂度是多少?
    【解决方案4】:

    看起来您可以将已处理的块存储在跳过列表中。块应按起始位置排序。然后要在每个步骤中找到重叠块,您应该在这个平均为 O(log n) 的跳过列表中进行搜索。您找到第一个重叠块,然后迭代到下一个,依此类推,直到遇到第一个非重叠块。

    因此平均而言,您可以获得 O(n * (log(n) + m)) 其中 m - 是重叠块的平均数。在最坏的情况下,你仍然会得到 O(n^2)。

    【讨论】:

      猜你喜欢
      • 2021-03-23
      • 2020-05-17
      • 1970-01-01
      • 2018-03-20
      • 2013-05-15
      • 2020-07-25
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多