【问题标题】:Retrieving maximum value from a range in unsorted array从未排序数组的范围中检索最大值
【发布时间】:2013-05-04 09:22:33
【问题描述】:

我有一个未排序的数组。我有许多查询,其中我给出了一个范围(表示为两个数组索引),然后必须返回该范围的最大值(即,来自数组的指定切片)。 例如:

array[]={23,17,9,45,78,2,4,6,90,1};
query(both inclusive): 2 6
answer: 78

我构建了哪种算法或数据结构来快速检索任意范围的最大值。 (有很多查询)

编辑: 我正在使用 C++

【问题讨论】:

  • 使用您正在使用的编程语言的内置max() 函数。这将是最快的。
  • @sudeepdino008 您使用的是哪种语言。
  • 我会尝试将列表转换为(index, value) 元组列表,按value 降序排序,然后在查询中迭代此列表并返回索引所在的第一个值在给定的范围内。但是,与整个列表相关的范围越小,这将变得越慢。对于较小的范围,在某些时候只线性查找最大值可能会更快。
  • 哈哈。这是关于 codechef 的编程问题之一。 ww2.codechef.com/MAY13/problems/MSTICK那就需要使用这种数据结构

标签: c++ arrays algorithm sorting data-structures


【解决方案1】:

我认为允许进行一些预处理。这是范围最小查询问题(这里是最大值)。 Good review of this problem at TopCoder。 合适的数据结构:段树和Sqrt-decomposition

#include <cstdio>
#include <iostream>
#include <algorithm>

#define N int(3e4)

using namespace std;

int act[N], len, sz, res[N];

int answer(int l, int r) {
        int ret = -1, i;
        for (i = l; i % sz && i <= r; i++)
                ret = max(ret, act[i]);
        for (; i + sz <= r + 1; i += sz)
                ret = max(ret, res[i / sz]);
        for (; i <= r; i++)
                ret = max(ret, act[i]);
        return ret;                                            
}

int main() {
        int i, m;
        cin >> m;
        for (i = 0; ; i++) {
                cin >> act[i];
                if (act[i] == -1)
                        break;
        }
        len = i;

        for (sz = 1; sz * sz < len; sz++);

        for (int j = i + 1; j < sz * sz; j++)
                act[j] = -1;

        for (int i = 0; i < sz * sz; i++)
                res[i / sz] = max(res[i / sz], act[i]);

        for (int i = 0; i + m <= len; i++)
                cout << answer(i, i + m - 1) << endl;          

        return 0;
}

【讨论】:

    【解决方案2】:

    mergesort n 获取范围的最后一个索引值,我将最大。

    数组[]={23,17,9,45,78,2,4,6,90,1}; 查询(含):2 6

    mergesort 返回第 6 个索引 var (index = 1 .. n)

    答案:78

    【讨论】:

    • 他会为每个查询做一个新的归并排序吗?在这里排序可能是最糟糕的主意
    【解决方案3】:

    假设这是你的数组array[]={23,17,9,45,78,2,4,6,90,1};

    如果您的数组不是那么大,我会为您提供预处理数组并获得另一个这样的数组:

    {0,0} = 23; //between arr[0] and arr[0]
    {0,1} = 23;
    {0,2} = 23;
    {0,3} = 45;
    
    {9,9} = 1;
    

    所以你的新数组将是newArr = {23,23,23,45,....., 1}

    你可以在O(1)中找到搜索,例如,4-5之间的最大值是newArr[4*array.length+5)-1]; 总共,对于 n 个查询,您将有 O(n)。

    空间是如果你有 10000(10^4) 整数,那么你的 newArr = 10^8 * 4B = 400MB,所以如果你有超过 10000 int,那么这行不通

    编辑:我想到了一些东西,但它与 MBo 提到的algorithm in Topcoder 相同。

    【讨论】:

    • 我有大约 (10^5) 长度的数组。
    猜你喜欢
    • 1970-01-01
    • 2018-05-14
    • 1970-01-01
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-05
    • 2022-12-09
    相关资源
    最近更新 更多