数组中前一个最新的更大元素

时间:2015-02-28 08:03:08

标签: algorithm

我尝试解决以下问题。给定每个元素的实数[7, 2, 4, 8, 1, 1, 6, 7, 4, 3, 1]数组,我需要找到数组中最近的前一个更大的元素。

例如,没有什么比第一个元素(7)更大,所以它有NaN。对于第二个元素(2),7更大。所以最后答案如下:

[NaN, 7, 7, NaN, 8, 8, 8, 8, 7, 4, 3, 1]。当然,我可以检查每个元素的所有前面的元素,但这在数组的元素数量方面是二次的。

我的另一种方法是维护先前元素的排序列表,然后选择大于当前的第一个元素。这听起来像是一个线性的日志(我不确定)。有没有更好的方法来解决这个问题?

4 个答案:

答案 0 :(得分:3)

这是一种方法

create a stack which is initially empty
for each number N in the array
{
    while the stack is not empty
    {
        if the top item on the stack T is greater than N
        {
            output T (leaving it on the stack)
            break
        }
        else
        {
            pop T off of the stack
        }
    }
    if the stack is empty
    {
        output NAN
    }
    push N onto the stack
}

获取样本数组[7,2,4,8,1,1,6,7,4,3,1],这里有算法如何解决它。

stack           N             output  
-               7               NAN 
7               2               7
7 2             4               7
7 4             8               NAN
8               1               8
8 1             1               8
8 1             6               8
8 6             7               8
8 7             4               7
8 7 4           3               4
8 7 4 3         1               3

理论上说,堆栈不需要保留小数,因为它们永远不会成为输出的一部分。例如,在序列7, 2, 4中,不需要2,因为任何小于2的数字也将小于4.因此堆栈只需要保留7和4。

复杂性分析

算法的时间复杂度可以显示为 O(n),如下所示:

  1. 确实有n次推送(输入数组中的每个数字都是 被推入堆栈一次,只有一次)
  2. 最多只有n个弹出窗口(一旦从堆栈中弹出一个数字, 它被丢弃了)
  3. 最多n次比较失败(因为数字已弹出 并且在比较失败后丢弃)
  4. 最多n次成功比较(自算法以来) 成功后移动到输入数组中的下一个数字 比较)
  5. 正好有n个输出操作(自算法以来) 为输入数组中的每个数字生成一个输出)
  6. 因此我们得出结论,该算法在大多数5n操作中执行以完成任务,这是 O(n)的时间复杂度。

答案 1 :(得分:2)

我们可以为每个数组元素保留其最新的更大元素的索引。当我们处理一个新元素x时,我们检查前一个元素y。如果y更大,那么我们找到了我们想要的东西。如果没有,我们检查哪个是y的最新更大元素的索引。我们继续,直到找到我们需要的元素及其索引。使用python:

a = [7, 2, 4, 8, 1, 1, 6, 7, 4, 3, 1]
idx, result = [], []
for i, v in enumerate(a, -1):
    while i >= 0 and v >= a[i]:
        i = idx[i]
    idx.append(i)
    result.append(a[i] if i >= 0 else None)

结果:

[None, 7, 7, None, 8, 8, 8, 8, 7, 4, 3]

算法是线性的。由于我们正在查找索引j中最新的较大元素,因此检查索引i > j未成功,从现在起i将指向比j更小的索引, j将不再被检查。

答案 2 :(得分:0)

为什么不定义变量'current_largest'并从左到右遍历数组?在每个元素处,当前最大值是最大值,如果当前元素较大,则将current_largest分配给当前元素。然后转到下一个元素。

编辑: 我只是重新阅读你的问题,我可能误解了它。你想找到以前更大的元素吗?

EDIT2: 在我看来,目前最大的方法将起作用。您只需要在为其指定新值之前记录current_largest。例如,在python中:

current_largest = 0
for current_element in elements:
    print("Largest previous is "+current_largest)
    if(current_element>current_largest):
        current_largest = current_element

如果你想要这些数组,那么只需将值推送到数组代替print语句。

答案 3 :(得分:0)

根据我对你的问题的最佳理解。以下是一个解决方案。 工作示例:JSFIDDLE

 var item = document.getElementById("myButton");
item.addEventListener("click", myFunction);
function myFunction() {
    var myItems = [7, 2, 4, 8, 1, 1, 6, 7, 4, 3, 1];
    var previousItem;
    var currentItem;
    var currentLargest;
    for (var i = 0; i < myItems.length; i++) {
        currentItem = myItems[i];
        if (i == 0) {
            previousItem = myItems[0];
            currentItem = myItems[0];
            myItems[i] = NaN;
        }
        else {
            if (currentItem < previousItem) {
                myItems[i] = previousItem;
                currentLargest = previousItem;
            }
            if (currentItem > currentLargest) {
                currentLargest = currentItem;
                myItems[i] = NaN;
            }
            else {
                myItems[i] = currentLargest;
            }
            previousItem = currentItem;
        }
    }
    var stringItems = myItems.join(",");
    document.getElementById("arrayAnswer").innerHTML = stringItems;
}