查找数组中存在大多数值的数组间隔

时间:2011-01-21 02:00:52

标签: arrays

实施例 排序位置矢量[4,5,9,30,31,32,34,40,47] 区间长度= 6

我想在任何给定的长度为6的间隔内找到最大值。在上面提到的例子中,间隔将是 [数组值 - 数组值+间隔长度:此数组中存在的#Values]

  • 4 - 10:3(4,5,9)
  • 5 - 11:2(5,9)
  • 9 - 15:1(9)
  • 30 - 36:4(30,31,32,34)
  • 31 - 37:3
  • 32 - 38:2
  • 34 - 40:2
  • 40 - 46:1
  • 47 - 53:0

答案应该是30-36,因为它的最大值是4。任何人对如何最佳地找到它有任何好的想法吗?

3 个答案:

答案 0 :(得分:0)

我不知道如何在O(n.k)时间内完成此操作,其中n是数组中的项目数,k是“间隔长度”。

  • 对于n中的每个元素,您需要检查“间隔”以查找下一个k元素。

我考虑过对数组进行预处理以获得间隔值矩阵,但这会与基本的朴素算法具有相同的复杂性。

答案 1 :(得分:0)

这是我能想到的最快的方式。另外,注意:您将间隔定义为6,但随后表示它包含项目30到36(即7项),所以我基于此编写此代码:

int GetInterval(const vector<int> &sortedList, int intervalLength)
{
  int lowest = sortedList[0];
  int highest = sortedList[sortedList.size()-1];
  vector<int> intervals(highest-lowest-intervalLength+1, 0);
  int max = 0;

  for(int i = 0; i < sortedList.size(); i++)
  {
    int base = sortedList[i] - lowest;
    for(int j = -intervalLength; j <= intervalLength; j++)
    {
      int index = i + j + base;
      if(index < 0 || index >= intervals.size()) continue;
      if(++intervals[index] > intervals[max]) max = index;
    }
  }

  return max + lowest;
}

所以,我实际上没有运行它,但它应该工作。它的大O是排序列表的长度乘以间隔长度。如果你将区间长度作为常数,则它是O(n)。希望这对你有用。另外,我希望c ++也适合你。

*注意它会返回间隔中的最小数字。

答案 2 :(得分:0)

反向扫描列表以消除一些回溯。

size_t find_interval(const std::vector& _positions, int _interval)
{
    assert(_positions.size() >= 2);

    size_t start_of_run = 0;
    size_t end_of_run;
    size_t idx;
    size_t run_length = 0;

    end_of_run = _positions.size() - 1;
    idx = end_of_run - 1;
    for(; idx >= 0; --idx)
    {
        if((_positions[end_of_run] - _positions[idx]) <= _interval)
        {
            // idx is still in the interval, see if it's the longest
            // run so far
            if((end_of_run - idx) > run_length)
            {
                start_of_run = idx;
                run_length = end_of_run - idx;
            }
        }
        else
        {
            // idx is out of the interval, so move end_of_run down to
            // make a new valid interval
            do
            {
                --end_of_run;
            } while((_positions[end_of_run] - _positions[idx]) > _interval);

            // we don't care about a run smaller than run_length, so move
            // idx to the shortest interesting run
            idx = end_of_run - run_length;
        }
    }

    return start_of_run;
}

使用end_of_runidx之间的二进制搜索可以更有效地更新end_of_run变量,但这会使算法更难理解。