题目描述
给你一个整数数组
nums
,返回 数组answer
,其中answer[i]
等于nums
中除nums[i]
之外其余各元素的乘积 。题目数据 保证 数组
nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。请 不要使用除法,且在
O(n)
时间复杂度内完成此题。示例 1:输入: nums =
[1,2,3,4]
输出:[24,12,8,6]
示例 2:输入: nums = [-1,1,0,-3,3] 输出: [0,0,9,0,0]
提示:
2 <= nums.length <=
-30 <= nums[i] <= 30
- 保证 数组
nums
之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内进阶:你可以在
O(1)
的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)
解题思路
要解决这个问题并且避免使用除法,我们可以利用前缀乘积和后缀乘积来计算每个位置的结果。我们可以按照以下步骤进行:
-
前缀乘积:
创建一个数组prefix
,其中prefix[i]
存储的是nums
中从0
到i-1
的元素乘积;初始化prefix[0]
为1
,表示没有元素前缀的乘积;遍历nums
数组,从左到右填充prefix
数组。 -
后缀乘积:
创建一个变量suffix
,用于计算从i+1
到数组末尾的乘积;遍历nums
数组,从右到左更新结果数组answer;
对于每个i
,answer[i]
是prefix[i]
和suffix
的乘积。
这种方法能够在 O(n) 时间复杂度内完成计算,且空间复杂度为 O(1),不考虑输出数组的额外空间。
复杂度分析
- 时间复杂度:O(n),因为我们分别进行两次线性遍历,一次计算前缀乘积,一次计算后缀乘积。
- 空间复杂度:O(1),不考虑输出数组的空间,使用了常量空间来存储中间结果。
代码实现
package org.zyf.javabasic.letcode.hot100.ordinaryarray;
import java.util.Arrays;
/**
* @program: zyfboot-javabasic
* @description: 除自身以外数组的乘积
* @author: zhangyanfeng
* @create: 2024-08-21 22:31
**/
public class ProductExceptSelfSolution {
public int[] productExceptSelf(int[] nums) {
int n = nums.length;
int[] answer = new int[n];
// 步骤 1:计算前缀乘积
// 初始化答案数组的第一个元素
answer[0] = 1;
// 计算前缀乘积
for (int i = 1; i < n; i++) {
answer[i] = answer[i - 1] * nums[i - 1];
}
// 步骤 2:计算后缀乘积并最终更新答案数组
int suffix = 1; // 从 1 开始,表示当前元素右侧的乘积
for (int i = n - 1; i >= 0; i--) {
// 更新答案数组的当前元素,乘以前缀乘积和后缀乘积
answer[i] = answer[i] * suffix;
// 更新后缀乘积为当前元素
suffix *= nums[i];
}
return answer;
}
public static void main(String[] args) {
ProductExceptSelfSolution solution = new ProductExceptSelfSolution();
// 测试用例 1
int[] nums1 = {1, 2, 3, 4};
int[] result1 = solution.productExceptSelf(nums1);
System.out.println(Arrays.toString(result1)); // 输出: [24, 12, 8, 6]
// 测试用例 2
int[] nums2 = {-1, 1, 0, -3, 3};
int[] result2 = solution.productExceptSelf(nums2);
System.out.println(Arrays.toString(result2)); // 输出: [0, 0, 9, 0, 0]
}
}
具体可参考:https://zyfcodes.blog.csdn.net/article/details/141401712