【问题标题】:spoj ARRAYSUB: O(n) Complexity Approachspoj ARRAYSUB:O(n) 复杂度方法
【发布时间】:2012-09-02 19:26:14
【问题描述】:

我试图在 spoj 上解决这个问题 http://spoj.pl/problems/ARRAYSUB

我用两种方法解决了这个问题

首先使用优化的蛮力。 其次在 k、2k、3k 等处取 Pivot 并找到最大值。

虽然在最坏的情况下两种解决方案都被接受,但复杂度为 O(n*k);

任何人都可以提出 O(n) 解决方案解决问题的方法吗?

下面是我的最坏情况复杂度 O(n*k) 的 Running Accepted 代码:

#include<iostream>
#include<cstdio>
#include<climits>
using namespace std;
main()
{
    long n;
    cin >> n;
    long *arr = new  long[n];
    for( long i=0;i<n;i++)
        cin >> arr[i];
     long k;
    cin >> k;
     long max=arr[0];
    for(long i=1;i<k;i++)
    {
        if(arr[i]>max)
            max=arr[i];
    }
    if(k!=n)
    cout<<max<<" ";
    else cout<<max;
    for( long i=k;i<n;i++)
    {
        if(arr[i-k]==max)
        {max=-1;
        for(int j=i-k+1;j<=i;j++)
        if(arr[j]>max)
        max=arr[j];
        if(i!=n)
        cout<<max<<" ";
        else cout<<max;

        }
        else{
        if(arr[i]>max)
        {   max=arr[i];

        if(i!=n)
        cout<<max<<" ";
        else 
        cout<<max;
        }
        else
        {
        if(i!=n)
        cout<<max<<" ";
        else cout<<max;}
        }
    }

        cout<<endl;
    return(0);
}

【问题讨论】:

    标签: c++ algorithm


    【解决方案1】:

    在O(n)时间内用来解决这个问题的数据结构是“deque”

    大多数人会认为的一种自然方式是尝试将队列大小保持与窗口大小相同。尝试摆脱这种想法并尝试跳出框框思考。去除冗余元素,只存储队列中需要考虑的元素,是实现下面高效 O(n) 解决方案的关键。

      void maxInWindow(vector<int> &A, int n, int k, vector<int> &B) {
      deque<int> Q;
      for (int i = 0; i < k; i++) {
        while (!Q.empty() && A[i] >= A[Q.back()])
          Q.pop_back();
        Q.push_back(i);
      }
      for (int i = k; i < n; i++) {
        B[i-k] = A[Q.front()];
        while (!Q.empty() && A[i] >= A[Q.back()])
          Q.pop_back();
        while (!Q.empty() && Q.front() <= i-k)
          Q.pop_front();
        Q.push_back(i);
      }
      B[n-k] = A[Q.front()];
      //B stores the maximum of every contiguous sub-array of size k    
    }
    

    解释:

    第一个 for 循环计算前“k”个元素的最大值并将索引存储在 Q.front() 中。这变为 B[0] = A[index]。 下一部分,如果 A[i] 大于先前存储的最大值,我们将从后面推入。 如果索引的值小于 i-k,则我们从前面弹出,这意味着它不再相关。

    【讨论】:

    • @sajalijain4 请更清楚地解释算法??我不是想从你那里得到编码器..我的摩托是知道方法..请详细解释一下。提前致谢
    • 我已经添加了一个解释。请告诉我是否可以理解
    • 这篇文章也是你的作品吗?那里的代码几乎相同。 articles.leetcode.com/sliding-window-maximum
    【解决方案2】:

    一种比蛮力更有效的方法是使用红黑树 (RB) 作为数据结构。因为 RB 树具有在 O(log n) 时间内插入、删除和查找最小值或最大值的特性,其中 n 是树中的节点数。

    尽管 AVL 树具有相同的属性,但与 RB 树相比,隐藏在大 O 后面的常数很大。

    问题的整体复杂度现在将变为 O(n lg k)。

    先在RB Tree中插入k个节点,然后使用find max得到最大元素。 (2 * log k) 其次,我们删除插入的第一个元素,然后插入一个新元素,然后查询最大元素。 (3 * log k)。按照相同的程序,我们大约需要 (3 * n * log k)。即 O(n* log k)。

    目前幼稚的蛮力解决方案未被接受,但该解决方案已被接受。

    【讨论】:

      猜你喜欢
      • 2011-06-05
      • 1970-01-01
      • 2015-06-12
      • 2020-11-14
      • 2020-12-24
      • 2021-06-22
      • 1970-01-01
      • 2014-03-23
      • 1970-01-01
      相关资源
      最近更新 更多