将给定数组中的所有零移动到末尾,并将每个非零元素替换为最接近的较大值(如果有)

Posted

技术标签:

【中文标题】将给定数组中的所有零移动到末尾,并将每个非零元素替换为最接近的较大值(如果有)【英文标题】:Move all zeroes in a given array to the end and replace each non-zero element with the closest greater value, if any 【发布时间】:2021-11-19 21:58:23 【问题描述】:

寻找以下问题的优化解决方案。

给定一个未排序的数组,我们需要将所有零移动到数组的末尾,同时找到每个元素的下一个最接近的更大数量(非零),如果没有下一个则返回相同的元素数组中某个元素的更大元素。

输入 = 6,1,5,0,0,3,8,6,4 输出= 8,3,6,4,8,6,4,0,0

我尝试了以下:

public class next_closest_element 

  public static void main(String[] arg) 
    int[] input = 6, 1, 5, 0, 0, 3, 8, 6, 4;
    Stack<Integer> stack = new Stack<Integer>();
    int k = 0;
    int count = 0;
    int last_index_value =input.length-1;

    for (int i = 0; i < input.length; i++) 
      if (input[i] != 0) 

        int j = i + 1;
        boolean flag = false;
        while (j < input.length && input[i] != 0) 

          if (input[j] > input[i]) 
            if (stack.empty() || !flag) 
              stack.push(input[j]);
              flag = true;
              j++;
             else if (stack.peek() > input[j]) 
              stack.pop();
              stack.push(input[j]);
              flag = true;
              j++;
             else 
              j++;
            
           else 
            j++;
          
        
        if (flag) 
          input[k] = stack.peek();
          k++;
        
        else 
          input[k]=input[i];
          k++;
        

      
      else
        count +=1;
      
    

    while(count>0)
      input[last_index_value]=0;
      last_index_value--;
      count--;
    
    for (int s :
      input) 
      System.out.println(s);
    
  


【问题讨论】:

当你说下一个更大的元素时,它应该在元素的右侧,或者它可以在任何地方? 根据示例,它看起来应该在右侧。如果我们忽略原始中的零,我们有[6, 1, 5, 3, 8, 6, 4] -&gt; [8, 3, 6, 4, 8, 6, 4]。对于索引65 &gt; 4 处的4,但似乎因为5 在索引6 的左侧,它被忽略了。 当我们从右到左遍历时,通过构建一个平衡的 BST 绝对可以在 O(N * log(N)) 时间内解决这个问题,但我的直觉告诉我,使用单端队列来进一步减少运行时可能是可能的......但是在绘制过程时,即使有两个双端队列,我最终也不得不在最坏的​​情况下进行 O(N) 插入/删除。 如果必须从右边取出下一个较大的,可以使用归并排序的合并功能来完成。这个问题类似于计数倒置,除了我们要进行计数这一事实。 @nice_dev 和 wLui155 是右侧的下一个更大的元素 【参考方案1】:

首先将零铲到右边是一种优化。

可能替换为下一个最接近的更大元素,我将其解释为下一个后续元素(正如您似乎所做的那样,否则最后 4 个可能已成为覆盖的 5 个)。

static int[] f(int[] values) 
    // In-situ (in-place) algorithm.

    int n = 0; // The count of non-zero values.
    for (int i = 0; i < values.length; ++i) 
        if (values[i] != 0) 
            values[n] = values[i];
            ++n;
        
    
    // Zero the rest:
    // (With a second array the remaining values from n upwards would
    // already be zero.)
    for (int i = n; i < values.length; ++i) 
        values[i] = 0;
    

    // 6, 1, 5, 0, 0, 3, 8, 6, 4 -> 6, 1, 5, 3, 8, 6, 4, [n] 0, 0
    // (First optimisation.) Now we only need to deal with n non-zero values.

    // Search the next (A) closest greatest (B) number, when found substitute.
    // Unoptimized:
    for (int i = 0; i < n; ++i) 
        int ithValue = values[i];
        boolean hasClosest = false;
        int closest = Integer.MAX_VALUE;
        for (int j = i + 1; j < n; ++j) 
            int jthValue = values[j];
            if (jthValue > ithValue && (!hasClosest || jthValue < closest)) 
                closest = jthValue;
                hasClosest = true;
                values[i] = jthValue;
            
        
    
    // 8, 3, 6, 4, 8, 6, 4, 0, 0
    return values;


public static void main(String[] args) 
    int[] input = 6, 1, 5, 0, 0, 3, 8, 6, 4;
    System.out.println(Arrays.toString(f(input)));

最后一块没有优化好。

“最近最大”的另一种解释:

    int[] sorted = Arrays.copyOf(values, n);
    Arrays.sort(sorted);
    for (int i = 0; i < n; ++i) 
        int j = Arrays.binarySearch(sorted, values[i] + 1);
        if (j < 0)  // Not found 1 greater.
            j = ~j; // Even greater.
        
        if (j < n) 
            values[i] = sorted[j];
        
    
    // 8, 3, 6, 4, 8, 8, 5, 0, 0

排序成本 O(N log N),循环 O(N) 次二分查找 O(log N) 也是如此。 所以它更快,消耗内存。但这与您的堆栈使用情况相当。

顺便说一句,您的代码的清理版本可能已放在 CodeReview 上。

【讨论】:

以上是关于将给定数组中的所有零移动到末尾,并将每个非零元素替换为最接近的较大值(如果有)的主要内容,如果未能解决你的问题,请参考以下文章

2021-10-31:移动零。给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。示例:输入: [0,1,0,3,12]。输出: [1,3,12,0,0]。说

在python中将所有零移动到数组的末尾

移动零

283. 移动零

移动零---简单

移动零