【问题标题】:for each element finding the closest greater element为每个元素找到最接近的更大元素
【发布时间】:2014-03-20 18:28:49
【问题描述】:

给定一个整数数组,我们如何获得每个元素的最接近的更大元素?例如,如果数组是A[] = {1,2,3,4,5},那么最接近A[0] is 2,对于A[1] its 3,对于A[2] its 4..等等。 有没有比O(N^2) 更有效的方法? 我想构建两个辅助数组,其中一个将具有当前元素左侧的所有元素并且小于它,而另一个将具有当前元素右侧的所有元素并且大于它..但无法进一步进行..这个想法是否正确? 谢谢。

【问题讨论】:

  • 对于数组 3,2,1,5,4,这是 A[0] 最接近的更大元素?
  • “最接近的更大元素”不只是 next 元素(至少,除了最后一个元素,在这种情况下它不存在)?或者,尽管您的示例已排序,但您的输入数组实际上可能是未排序的?如果是这种情况,只需按照以下答案中的建议对数组进行排序...然后A[x] 的“最接近的更大元素”是A[x+1],只要您小心不要跑出数组的末尾...
  • 作为第二个澄清,“最接近的更大元素”是否意味着 a) 在其数组位置中最接近参考元素的元素,但在数值上大于该元素,或者 b) 中的元素比参考元素大最小边距的数组,还是 c) 其他?

标签: algorithm sorting


【解决方案1】:

对于another question,我描述了如何为每个元素找到其右侧最左边的较大元素。这可以使用 O(n) 中的堆栈来完成。

您可以稍微修改算法,以便在每次迭代中您都知道如何关闭右边的第一个元素。

然后你只需应用它两次,一次使用数组,一次使用它的反向,然后将具有最小距离的元素作为结果。

运行时间:O(n)

【讨论】:

    【解决方案2】:

    O(n log n) 时间对数组进行排序。对于输入数组中的每个元素(其中N),在排序后的数组中进行二进制搜索(O(log n))。所以总复杂度是O(n log n)+O(n log n) = O(n log n)。根据您的具体需要进行优化;例如,如果您知道输入数组以某种方式排序,则查找相应的最接近的较大元素可能比使用二分查找更快。

    【讨论】:

      【解决方案3】:

      a) 如果多次检索:

      1. 对数组进行排序:O(n*log(N));将 UNDEF 添加到数组的右端
      2. 查找 i:元素的位置 O(log(N))
      3. 返回 arr[i+1];

      时间:O(n*log(N)) 用于准备,O(log(N)) 用于检索;

      b) 如果进行单次检索:

      int rc = MAXINT;
      foreach x (array) 
        if(x > input_val && x < rc)
          rc = x;
      

      时间:O(N)

      【讨论】:

        【解决方案4】:

        线性时间两遍算法(在 Delphi 中)

        var
          A, B: TArray<Integer>;
          Stack: TStack<Integer>;
          i, candidate: Integer;
        begin
          //source array
          A := TArray<Integer>.Create(4, 2, 5, 2, 1, 6, 3, 2);
        
          //array for positions of closest greater elements
          B := TArray<Integer>.Create(-1, -1, -1, -1, -1, -1, -1, -1);
        
          //elements that pretend to be greater
          Stack := TStack<Integer>.Create;
        
          for i := 0 to High(A) do begin
            while (Stack.Count > 0) and (A[Stack.Peek] < A[i]) do
              B[Stack.Pop] := i;
            Stack.Push(i);
          end;
          //now B contains positions of greater elements to the right
          // {2,2,5,5,5,-1,-1,-1} 
          //-1 for elements without greater right neighbour
        
          //now walk right to left, find greater right neighbour, but use it
          //if it is CLOSER than right one
          for i := High(A) downto 0 do begin
            while (Stack.Count > 0) and (A[Stack.Peek] < A[i]) do begin
              candidate := Stack.Pop;
              if (B[candidate] = -1) or (B[candidate] - candidate > candidate - i) then
                B[candidate] := i;
            end;
            Stack.Push(i);
          end;
        // Result positions: {2,2,5,2,5,-1,5,6}
        

        【讨论】:

          猜你喜欢
          • 2013-11-17
          • 1970-01-01
          • 1970-01-01
          • 2023-04-09
          • 2022-12-31
          • 1970-01-01
          • 2021-06-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多