返回

在 JavaScript 中运用前缀积和后缀积破解 LeetCode 乘积数组难题

前端

引言

在编程领域,算法的巧妙应用往往能带来意想不到的解题效率提升。LeetCode 作为算法练习平台,汇集了大量精彩的题目,吸引着程序员们不断挑战和学习。本文将聚焦于 LeetCode 中一个颇具代表性的难题——乘积数组,并深入剖析如何运用前缀积和后缀积算法来破解这一难题。

问题

乘积数组问题的目标是给定一个整数数组 nums,其中每个元素都代表一个正整数,求出一个新数组 answer,其中 answer[i] 表示数组 nums 中除 nums[i] 自身以外所有元素的乘积。

算法原理

解决这一难题的关键在于理解前缀积和后缀积的概念。前缀积数组 pre 存储着从数组第一个元素到当前元素的乘积(不包含当前元素),而后缀积数组 post 存储着从当前元素到数组最后一个元素的乘积(不包含当前元素)。

算法步骤

  1. 初始化前缀积数组 pre 和后缀积数组 post
const pre = new Array(nums.length).fill(1);
const post = new Array(nums.length).fill(1);
  1. 计算前缀积:
for (let i = 1; i < nums.length; i++) {
  pre[i] = pre[i - 1] * nums[i - 1];
}
  1. 计算后缀积:
for (let i = nums.length - 2; i >= 0; i--) {
  post[i] = post[i + 1] * nums[i + 1];
}
  1. 计算答案数组 answer
for (let i = 0; i < nums.length; i++) {
  answer[i] = pre[i] * post[i];
}

滚动变量的优化

为了进一步优化算法,我们可以使用滚动变量 prod 来替代 pre 数组。prod 始终存储着从数组第一个元素到当前元素的乘积,每一步计算完当前元素的前缀积后,直接用 prod 乘以当前元素即可。

let prod = 1;
for (let i = 0; i < nums.length; i++) {
  answer[i] = prod;
  prod *= nums[i];
}

prod = 1;
for (let i = nums.length - 1; i >= 0; i--) {
  answer[i] *= prod;
  prod *= nums[i];
}

代码实现

/**
 * @param {number[]} nums
 * @return {number[]}
 */
const productExceptSelf = (nums) => {
  const answer = new Array(nums.length).fill(1);
  let prod = 1;
  for (let i = 0; i < nums.length; i++) {
    answer[i] = prod;
    prod *= nums[i];
  }

  prod = 1;
  for (let i = nums.length - 1; i >= 0; i--) {
    answer[i] *= prod;
    prod *= nums[i];
  }

  return answer;
};

结语

通过对前缀积和后缀积算法的深入理解和巧妙应用,我们成功破解了 LeetCode 中的乘积数组难题。这一算法不仅展现了算法的巧妙性,也启发了我们解决问题的思路。在实际编程中,选择合适的算法并优化其性能至关重要。希望本文能对各位程序员有所启发和帮助,让我们在算法的海洋中不断探索和成长。