【问题标题】:Algorithm: For each element of an array, find out the biggest value on its left side and less than itself算法:对于数组的每个元素,找出其左侧的最大值且小于自身的值
【发布时间】:2017-04-05 17:32:20
【问题描述】:

例如,给定一个数组:

[1, 2, 5, 4, 2, 6, 7, 3]

找出每个元素在其左侧且小于自身的最大值(如果不存在此类元素,则为 -1):

[-1,1, 2, 2, 1, 5, 6, 2]

什么是最佳算法?有没有比O(n*log(n))更好的算法?

【问题讨论】:

  • 什么编程语言?
  • @RomanPerekhrest 任何你喜欢 c++、ruby、java 的人。
  • O(n log n) 算法会是什么样子?一个简单的算法会产生 O(n^2) 的运行时界限。
  • @David,我认为如果您提供当前解决此问题的方法并将此问题移至 Code Review 站点会更好
  • 很抱歉问题的描述很糟糕。谢谢大家的建议。我会阅读指南以便将来更好地提问。 :)

标签: arrays algorithm


【解决方案1】:

Bruteforce 算法对数组进行迭代,将访问过的元素一一搜索并与当前元素进行比较。因此这是O(n^2) 算法。

加快进程的关键是搜索部分。我们必须充分利用我们已经已知的东西,也就是我们访问过的元素。

那么基本算法是这样的:

magic = new magic_data_structure
result = []
for x in input_array:
    y = magic.find_largest_but_less_than_current(x)
    result.push(y)
    magic.inesrt(x)

所以我们需要一个具有插入和搜索复杂度O(logn) 的数据结构。这通常是一个平衡的搜索树。例如,我们可以使用红黑树。

为了简单起见,我们可以使用 c++ stl 中的set。详情请看以下代码。

示例链接:http://ideone.com/5OIBCp

#include <bits/stdc++.h>
using namespace std;

using vi = vector <int>;

set <int> s;

vi foo(vi const &a) {
    vi ret;
    s.clear();
    for (auto const x: a) {
        auto it = s.lower_bound(x);
        if (it != begin(s)) {
            it = prev(it);
            ret.push_back(*it);
        } else {
            ret.push_back(-1);
        }
        s.insert(x);
    }
    return ret;
}

int main() {
    vi a = {1, 2, 5, 4, 2, 6, 7, 3};
    vi b = foo(a);
    for (auto x: b) printf("%d ", x); puts("");
    return 0;
}

https://en.wikipedia.org/wiki/Self-balancing_binary_search_tree

【讨论】:

  • 这太棒了,很清楚!我没想到会有这么快速简洁的可运行代码。 :)
  • @David,欢迎来到 SO。如此庞大而才华横溢的社区,您应该会很快得到回应。
  • @delta,您在那里编写的非常好的 c++ 代码。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2014-11-08
  • 2014-06-02
  • 1970-01-01
  • 2022-12-31
  • 1970-01-01
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多