将给定数组中的所有零移动到末尾,并将每个非零元素替换为最接近的较大值(如果有)
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] -> [8, 3, 6, 4, 8, 6, 4]
。对于索引6
、5 > 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]。说