【问题标题】:How to find maximum element on left hand side of an element which is smaller than the element?如何在小于元素的元素的左侧找到最大元素?
【发布时间】:2014-11-08 05:01:27
【问题描述】:

假设我有一个这样的整数数组:

{ 3, 1, 6, 8, 2, 0, 1 }

我需要在每个元素的左侧找到小于该元素的最大元素,或者如果该最大元素不存在,则打印-1。所以,这个问题的解决方案是:

{ -1, -1, 3, 6, 1, -1, 0 }

我可以在O(n^2) 中使用两个循环来解决这个问题。内循环将找到小于给定元素的最大元素。但是有没有更好的方法来解决这个问题?

【问题讨论】:

  • 我认为有一个错误......也许解决方案应该是 `{-1, -1, 3, 6, 1, -1, 0 } 而不是?
  • @Multithreader:感谢您的指出。你是对的。
  • @DavidEisenstat:这与您提到的问题不同。我不认为它是重复的。

标签: java c arrays algorithm max


【解决方案1】:

虽然这个问题与finding the rightmost element on the left hand side that is smaller 无关,这是一个涉及堆栈的可爱线性时间算法的问题,但它是密切相关的。要解决此问题,请按值对数组索引和值对进行排序,然后运行链接问题中的算法,将索引视为值。这避免了二叉搜索树强加的常数因子。

由于对不同元素进行排序可以线性时间简化为这个问题,O(sort(n)) 的运行时间或多或少是最优的。

Python 实现(比预期更微妙;注意sorted 不得重新排列比较相等的元素)。

def alg(lst):
    indexes = sorted(range(len(lst) - 1, -1, -1), key=lst.__getitem__)
    stack = []
    out = [-1] * len(lst)
    for i in indexes:
        while stack and i < stack[-1]:
            del stack[-1]
        if stack:
            out[i] = lst[stack[-1]]
        stack.append(i)
    return out


print(alg([3, 1, 6, 8, 2, 0, 1]))

【讨论】:

  • 对于给定的输入,索引结果是 [5,6,1,4,0​​,2,3] 而不是 [5,1,6,4,0,2,3] ,请问为什么在python中排序是一种稳定的排序,如果后者出现,代码会失败。您也可以在此处查看 - onlinegdb.com/H16wzVhed。由于我上面提到的原因,这个 sol 在网上评委中失败了。如果您想在最后验证相同,这里是链接 - practice.geeksforgeeks.org/problems/smaller-on-left2036/0/…
  • @Varun 我们正在对数组[6, 5, 4, 3, 2, 1, 0] 进行排序,因此稳定排序必须将6 放在1 之前,因为它在初始列表中就是这样。
  • 通常我用java编写代码,因为这段代码是用python编写的,我发现它有点混乱。我看到您正在从末尾迭代数组以根据值对其进行排序。但是,如果我将其更改为 indexs = sorted(range(0, len(lst), 1), key=lst.__getitem__),则索引现在是 [5,1,6,4,0,2,3] 而不是[5,6,1,4,0​​,2,3]。你开始从右边对数组进行排序有什么原因吗?如果数组从左开始排序,则生成的最终解是 [-1, -1, 3, 6, 1, -1, 1],这似乎是错误的。
  • @Varun 在某种意义上,排序顺序对输入元素造成了极小的扰动。通过将更大的索引按等于的顺序放在第一位,我们实质上是在让它们比较小于它们之前的索引。如果我们以另一种方式进行,那么在某种意义上,扰动将使较早的元素有资格作为后面的最大值。除了稳定的排序,您还可以使用 (lst[i], -i) 作为排序键。
【解决方案2】:

您可以将目前找到的数字存储在树状图中。将它们的索引与数字一起存储。当您找到索引i 处的数字时,在树中查找低于array[i] 的最高数字。使用lowerEntry可以让你在Log2N时间内完成,使得整体时序N*Log2N

【讨论】:

    【解决方案3】:

    步骤:

    1:对于第一个元素,我们可以将 -1 附加到我们的答案中。

    2:循环 i 遍历列表中的第一个元素,并不断将第 (i - 1) 个元素添加到 Treeset。

    3:要找到最大的小元素,我们可以通过 set.lower(元素)

    4:如果结果为 null,则添加 -1。

    这是一个实现

        StringBuilder b = new StringBuilder();
        TreeSet<Integer> set = new TreeSet<>();
        b.append(-1);
        b.append(" ");
        for(int i = 1; i<a.length; i++){
            set.add(a[i-1]);
            Integer result = set.lower(a[i]);
            if(result != null)
                b.append(result);
            else
                b.append(-1);
            b.append(" ");
        }
    

    【讨论】:

      猜你喜欢
      • 2021-12-06
      • 2022-12-31
      • 2021-11-07
      • 1970-01-01
      • 1970-01-01
      • 2015-03-11
      • 1970-01-01
      • 2015-08-22
      • 1970-01-01
      相关资源
      最近更新 更多