得到“朋友”塔的数量

时间:2014-04-04 05:53:50

标签: algorithm data-structures

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

两个塔 a,b 被视为朋友iff:

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

有多少`友谊'在那里?

解决方案很简单:

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,该程序将占用RAM;为了减少这一点,我使用队列来增加塔的高度而不是数组(当q.size()== k时,只需要q.pop())。使用天真解决方案检查大k的第三个条件必须花费时间。

2 个答案:

答案 0 :(得分:0)

您可以使用deque来提供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  

这样可以在双色显示屏的头部保留最大元素的索引,这样就可以确定 - 两个塔之间的值是否更大

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

答案 1 :(得分:0)

在阐述我的评论时,您可以使用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()