【问题标题】:Getting the number of "friend" tower获取“朋友”塔的数量
【发布时间】:2014-05-16 06:49:45
【问题描述】:

给定n 塔,编号为 1、2、3、...、n,其高度(h[i] = towers[i] 的高度)和数字 k。

两塔a, b 被认为是朋友当且仅当:

  • a - b = k
  • h[a] == h[b]
  • max(h[a+1], h[a+2] ... h[b - 1])

有多少“友谊”?

解决方法很简单:

for i = 1, 2, 3, 4, 5, ..., n - k:
    if h[i] == h[i+k]:
        for j in range[i, i+k] :
             MAX = max(MAX, h[j]
        if MAX <= h[i]:
             ans++

但我希望以最有效的方式解决问题。请帮忙。

对于大的n,程序会吃掉内存;为了减少这种情况,我使用队列而不是数组来添加塔的高度(当 q.size() == k,Just q.pop() 时)。用天真的解决方案检查具有大 k 的第 3 个条件必须花费时间。

【问题讨论】:

  • 您可以使用this question 的答案来有效地获得滑动最大值(问题是关于最小值,但这种变化很简单)。然后你可以在O(n)时间解决这个问题。
  • “对于大的 n,程序会吃掉 RAM”:你能解释一下吗?该算法不使用额外的存储空间!并且使用双端队列并不会减少存储空间!
  • 因为 n 与 k 相比非常大,所以如果我使用数组,我必须将所有数字存储到数组 -> 浪费
  • 我解决了!感谢您的链接@Heuster

标签: algorithm data-structures


【解决方案1】:

详细说明我的评论,您可以使用this question 的答案来构建一个队列,该队列可以跟踪两个塔之间的最大元素。移动到下一个元素只需要O(1) 摊销时间。我用伪代码做了一个简单的实现,假设该语言支持标准堆栈(如果不支持会感到惊讶)。有关说明,请参阅linked answer

class TupleStack
    Stack stack

    void push(int x)
        if stack.isEmpty()
            stack.push((value: x, max: x))
        else 
            stack.push((value: x, max: max(x, stack.peek().max))

    int pop()
        return stack.pop().value

    bool isEmpty()
        return stack.isEmpty()

    int getMax()
        if isEmpty()
            return -infinity
        else
            return stack.peek().max

class MaxQueue
    TupleStack stack1
    TupleStack stack2

    void enqueue(int x)
        stack1.push(x)

    int dequeue()
        if stack2.isEmpty()
            while !stack1.isEmpty()
                stack2.push(stack1.pop())
        return stack2.pop()

    int getMax()
        return max(stack1.getMax(), stack2.getMax())

您的算法现在非常简单。将第一个 k 元素放入队列中。之后,重复检查距离k 处的两个塔是否具有相同的高度,检查其间的最大值(即队列的最大值)是否最多为它们的高度,然后移动到接下来的两个塔。更新队列需要O(1) 摊销时间,所以这个算法运行在O(n),这显然是最优的。

MaxQueue queue
for (int i = 1; i <= k; i++)    // add first k towers to queue
    queue.enqueue(h[i])
for (int i = k+1; i <= n; i++)
    if h[i] == h[i-k] and h[i] >= queue.getMax()
        ans++
    queue.enqueue(h[i])
    queue.dequeue()

【讨论】:

  • 嗨..你能编辑这个答案吗?我想删除我的反对票。
【解决方案2】:

您可以使用双端队列来提供 O(n) 算法。
每一步:

Remove too old elements from the deque head  
       (if currentindex - index >= k)  
Remove elements from tail that have no chance to become maximum 
       in the k-size window (those < currentvalue)  
Add new element (index) to the deque tail  

这会在双端队列头部的 k 大小窗口中保留最大元素的索引,因此您可以确定 - 两个塔之间是否存在更大的值

用伪代码描述(滑动最小值)算法: Can min/max of moving window achieve in O(N)?

【讨论】:

  • 不知道为什么这被否决了。这是正确的答案(尽管它的工作原理可能更明确一点)。
  • 此问题不需要 Deque。检查我的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多