比较数组中的相邻元素并选择每对中较小的一个

时间:2019-12-07 08:08:16

标签: javascript arrays algorithm for-loop break

我正在学习JS算法课程。这是教员针对问题的解决方案,它已经成功运行:

function arrayPreviousLess(items) {
  const lessThanList = []

  for (let i = items.length - 1; i >= 0; i--) {
    for (let j = i; j >= 0; j--) {
      if (items[i] > items[j]) {
        lessThanList.unshift(items[j])
        break
      } else if (j === 0) {
        lessThanList.unshift(-1)
      }
    }
  }

  return lessThanList
}


console.log(arrayPreviousLess([3, 5, 2, 4, 5]))

此代码比较相邻的数组项。如果上一项小于下一项,则返回较小的项。由于错误原因,它必须返回-1,如下例所示:

输入:

[3,5,2,4,5] 

输出:

[-1,3,-1,2,4]

我正在理解所有内容,除了循环中break的目的是什么?当我删除此break时,它的工作方式相同。

1 个答案:

答案 0 :(得分:1)

鉴于相邻对的问题描述,您所显示的算法没有多大意义。除了break之外,没有理由使用嵌套循环,除非目的是将每个元素与其先前元素的 all 比较,在这种情况下是正确的。无论哪种方式,unshift都比push慢得多,并且我认为无论采用哪种算法,都没有理由诉诸该功能,也没有看到反向外循环背后的原因。

我将使用map为相邻对编写函数。我们可以一次迭代地完成此操作。

const arrayPreviousLess = a => a.map((e, i) => a[i-1] < e ? a[i-1] : -1);

[
  [3, 5, 2, 4, 5],
  [1],
  [1, 2],
  [2, 1],
  [1, 2, 3],
  [3, 2, 1],
  [3, 2, 3],
  [3, 1, 6, 4, 5],
].forEach(e => console.log(`[${e}] => [${arrayPreviousLess(e)}]`));

另一方面,如果问题是将每个元素与其左侧的所有元素进行比较,则我将修改讲师的解决方案,至少避免使用unshift并从前向后遍历参数数组。 / p>

const arrayPreviousLess = a => a.map((e, i) => {
  while (i--) {
    if (a[i] < e) return a[i];
  }

  return -1;
});

[
  [3, 5, 2, 4, 5],
  [1],
  [1, 2],
  [2, 1],
  [1, 2, 3],
  [3, 2, 1],
  [3, 2, 3],
  [3, 1, 6, 4, 5],
].forEach(e => console.log(`[${e}] => [${arrayPreviousLess(e)}]`));

该算法仍然是二次方的,但是有一个使用堆栈的线性算法。对于每个元素,当堆栈不为空且当前元素小于堆栈顶部时,弹出堆栈。最终,堆栈将变空或其顶部将包含先前的较小元素。如果堆栈变空,则将元素映射到-1,否则将元素映射到先前的较小元素。最后,将当前元素推入堆栈。

const arrayPreviousLess = a => {
  const stack = [];  
  return a.map(e => {
    while (stack.length && e < stack[stack.length-1]) {
      stack.pop();
    }

    return stack.push(e) > 1 ? stack[stack.length-2] : -1;
  });
};

[
  [3, 5, 2, 4, 5],
  [1],
  [1, 2],
  [2, 1],
  [1, 2, 3],
  [3, 2, 1],
  [3, 2, 3],
  [3, 1, 6, 4, 5],
].forEach(e => console.log(`[${e}] => [${arrayPreviousLess(e)}]`));

这背后的直觉是,当前元素后面的任何大于它的先前元素都不能成为先前的最小候选。我们可以丢弃它们。本质上,我们保留了元素数量最少的候选者的历史,并在保证可以有更小的元素之前就放弃任何候选者。