给定一个唯一正整数数组,为每个元素找到最近的较小元素,但距离至少为 k
Posted
技术标签:
【中文标题】给定一个唯一正整数数组,为每个元素找到最近的较小元素,但距离至少为 k【英文标题】:Given an array of unique positive integers, find the closest smaller element for each element, but at a distance of atleast k 【发布时间】:2016-10-09 01:13:51 【问题描述】:我所指的问题类似于this one。唯一的区别是 1.) 从当前元素到我们选择的最近的较小元素应该有至少“k”个单位的距离。 2.) 可以从任一方向、向左或向右拾取元素。例如,如果 k=4 并且在当前元素旁边有一个较小的元素,我们不能选择它,因为它太靠近了。
我尝试以与其他解决方案相同的方式实现它。我所做的更改是,每次从堆栈中删除一个元素时,如果它实际上小于当前元素但仅仅因为它比 k 个单位更近而被删除,那么一旦我找到答案,我就会将该元素添加回堆栈当前元素,然后移动到下一个元素。这似乎可行,但我确信有更有效的方法来解决这个问题。任何建议都会非常有帮助。
【问题讨论】:
你的距离是标量还是方向?例如。在 [1, 0, 3, 1] 中距离为 1 的 3 的最近最小元素是前面的 0 还是后面的 1?距离-1呢? 解决链接的问题,然后在回答查询之前将k添加到每个查询的索引中。 @le_m 距离的方向无关紧要。它可以在左边或右边。在您的情况下,您可以选择 0 或 1。 @j_random_hacker 我认为这行不通。当您将 k 添加到查询中时,您会找到具有不同值的完全不同元素的答案。 @HarshaReaper "唯一的区别是......" - 显然有两个区别,1. 最小距离 k 和 2. 你想找到最近的更小的元素在两个方向上,与仅执行前向遍历的链接问题相反。正确的?如果是,请更新您的问题。 【参考方案1】:运行时间和空间复杂度为 O(n) 的解决方案
仅前向遍历: 以下算法是对Given an array, find out the next smaller element for each element 答案的修改,并为输入数组的每个元素返回最近的较小后继元素,并保证元素与后继元素之间的最小距离:
// Traversal in forward direction only:
function smaller(array, distance)
var length = array.length,
result = new Array(length).fill(null),
stack = [];
// Forward pass:
for (var i = 0, j = distance; j < length; ++i, ++j)
while (stack.length > 0 && array[j] < array[stack[stack.length - 1]])
result[stack.pop()] = array[j];
stack.push(i);
return result;
console.log(smaller([0, 2, 1], 0)); // [null, 1, null]
console.log(smaller([5, 2, 1, 7, 6, 0], 1)); // [1, 0, 0, 0, null, null]
前向和后向遍历:以下算法为输入数组的每个元素返回最近的较小后继或前驱,并保证元素与后继之间的最小距离或前任。
它的工作原理类似于第一个算法,但在两个方向上遍历数组并存储索引,而不是较小元素的值。在最后的第三遍中,从两遍的结果中选择最近的较小元素:
// Traversal in both directions:
function smaller(array, distance)
var length = array.length,
forward = new Array(length).fill(null),
backward = new Array(length).fill(null),
stack = [];
// Forward pass:
for (var i = 0, j = distance; j < length; ++i, ++j)
while (stack.length > 0 && array[j] < array[stack[stack.length - 1]])
forward[stack.pop()] = j;
stack.push(i);
// Backward pass:
stack = [];
for (var i = length - 1, j = length - distance - 1; j >= 0; --i, --j)
while (stack.length > 0 && array[j] < array[stack[stack.length - 1]])
backward[stack.pop()] = j;
stack.push(i);
// Pick closest elements from both passes:
for (var i = 0; i < length; ++i)
if (backward[i] !== null)
if (forward[i] !== null && forward[i] - i < i - backward[i])
forward[i] = array[forward[i]];
else
forward[i] = array[backward[i]];
else if (forward[i] !== null)
forward[i] = array[forward[i]];
return forward;
console.log(smaller([0, 2, 1], 0)); // [null, 0, 0]
console.log(smaller([5, 2, 1, 7, 6, 0], 1)); // [1, 0, 0, 2, 1, null]
【讨论】:
以上是关于给定一个唯一正整数数组,为每个元素找到最近的较小元素,但距离至少为 k的主要内容,如果未能解决你的问题,请参考以下文章
2021-07-16:三个无重叠子数组的最大和。给定数组 nums 由正整数组成,找到三个互不重叠的子数组的最大和。每个子数组的长度为k,我们要使这3*k个项的和最大化。返回每个区间起始索引的列表(索