【问题标题】:Given an array A,compute B s.t B[i] stores the nearest element to the left of A[i] which is smaller than A[i]给定一个数组 A,计算 B s.t B[i] 存储离 A[i] 左边最近且小于 A[i] 的元素
【发布时间】:2011-06-26 09:57:06
【问题描述】:

给定一个数组A[1..n],我们想要计算另一个数组B[1..n],使得B[i] 存储最接近A[i] 左侧的元素,该元素小于A[i]。 时间复杂度应该是O(n)

(对于i>1,如果左边没有这么小的元素,那么B[i]只包含A[i]B[1]=A[1]。)

例子:

输入:6,9,12,17,11
输出:6,6,9,12,9

我正在考虑实现一个堆栈,
A[1] 放入B[1],然后推入堆栈。
用于填充B[i],将A[i] 与堆栈元素进行比较并弹出直到你得到更小的元素。
最后将A[i] 推入堆栈。

上述方法是否正确,是否有更便宜的解决方案?

【问题讨论】:

  • 你的意思是:'到 A[i] 的 left'。如果没有这样的元素,您还必须说出您想要的内容(例如,对于您的示例中的 B[1],如果没有更小的元素,则对于 i>1)。
  • 这个问题似乎不明确。正如 TonyK 指出的那样,您的示例不符合要求,此外,不清楚 B[0] 应该是什么,因为 A 中没有小于 6 的元素。请先澄清问题描述。
  • 请让我知道它是否仍然模棱两可。我从右到左更改了。我认为现在序列很好。让 B[1] 成为 A[1] 只是因为它没有剩下的元素。

标签: arrays algorithm stack


【解决方案1】:

您的堆栈方法是正确的。它之所以有效,是因为如果您弹出一个大于A[i] 的元素,那么A[i] 之后的任何元素都将永远不需要该元素,因为您可以只使用A[i]

每个元素只被访问两次,所以这是O(n)

【讨论】:

  • 很高兴听到这个,我也很好奇替代解决方案,它可以避免堆栈并且更便宜。
【解决方案2】:

堆栈方法不正确。看看如果输入 6、9、12、17、11、15 会发生什么。当您将使用 15 时,您的堆栈已被遗忘约 12 和 17。但 A[5] 的最近的小左侧元素是 12。

Saeed 算法也不对。试着计算一下。

正确的答案可能是这样的

b[1] = a[1];
s[1] = 1;
for (i=2; i<=n; i+=1) { 
  j = i - 1;
  while (j>1){
    if (a[j]<a[i]) {
      b[i] = a[j];
      s[i] = j;
      break;
    } else {
      j = s[j];
    }
  }
  if (j = 1) {
    b[i] = a[j];
    s[i] = j;
  }
}

我不确定,但它的复杂度为 O(n)。

【讨论】:

  • 最近(左)的 15,小于 11 而不是 12。数组的输出应该是 6,6,9,12,9,11。
  • @Maxim Welikobratov 如果问题是在数组中的每个元素的左侧找到最大的较小元素,那么基于堆栈的方法将不起作用,但问题是要找到最近的元素小于当前元素的左边,它将起作用。
【解决方案3】:
B[1]=A[1]
push(B[1])
for i=2 to n do
{
    while(A[i] > stack_top ANS stack_top!=NULL)
       pop()
    if(stack_top=NULL)
        B[i]=A[i]
    else
        B[i]=stack_top
    push(A[i])
}

正如 IVlad 指出的那样,每个元素最多被推送和弹出一次,时间是 O(n)。

如果有错误请纠正我,我很好奇任何避免堆栈且更便宜的替代解决方案。

【讨论】:

    猜你喜欢
    • 2021-11-01
    • 1970-01-01
    • 2014-12-29
    • 2021-11-02
    • 2021-04-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多