除自身以外数组的乘积[中等]

优质博文:IT-BLOG-CN

一、题目

给你一个整数数组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 <= 105
-30 <= nums[i] <= 30

保证数组nums之中任意元素的全部前缀元素和后缀的乘积都在32位整数范围内

进阶:你可以在O(1)的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)

二、代码

【1】创建左右乘积列表: 我们不能将所有数字的乘积除以给定索引处的数字得到相应的答案,而是利用索引左侧所有数字的乘积和右侧所有数字的乘积(即前缀与后缀)相乘得到答案 。初始化两个数组LeftRight,对于指定的下表ileft[i]代表i左侧所有数据的乘积,right[i]代表i右侧所有数据的乘积。我们利用循环将数据填充到lfet[]right[]数组中,然后将left[i]right[i]相乘就是i的左右乘积。

java 复制代码
class Solution {
    public int[] productExceptSelf(int[] nums) {
        if (nums == null || nums.length == 0) {
            return null;
        }

        // 我们使用数组,也就是当前数字的left[] 和 right[] 数组,分别存储左右两边的和;
        int len = nums.length;
        int res[] = new int[len];
        int left[] = new int[len];
        int right[] = new int[len];
        // 第一个数之前的数的乘积为1,所以先给个默认值
        left[0] = 1;
        for (int i = 1; i < len; i++) {
            // left 中保存的是i之前所有数的乘积
            left[i] = left[i - 1] * nums[i - 1];
        }
        // 最有边的数也保存为1
        right[len - 1] = 1;
        for (int i = len - 2; i >= 0; i--) {
            right[i] = right[i + 1] * nums[i + 1];
        }

        for (int i = 0; i < len; i++) {
            res[i] = left[i] * right[i];
        }
        return res;
    }
}

时间复杂度: O(N),其中N指的是数组nums的大小。预处理LR数组以及最后的遍历计算都是O(N)的时间复杂度。
空间复杂度: O(N),其中N指的是数组nums的大小。使用了LR数组去构造答案,LR数组的长度为数组nums的大小。

【2】空间复杂度O(1)的方法: 由于输出数组不算在空间复杂度内 ,那么我们可以将LR数组用输出数组来计算。先把输出数组当作L数组来计算,然后再动态构造R数组得到结果。

java 复制代码
class Solution {
    public int[] productExceptSelf(int[] nums) {
        if (nums == null || nums.length == 0) {
            return null;
        }

        // 因为返回的数组可以不算在空间复杂度中,所以可以作为临时变量存放left[]数据
        int len = nums.length;
        int res[] = new int[len];
                // // 第一个数之前的数的乘积为1,所以先给个默认值
        res[0] = 1;
        for (int i = 1; i < len; i++) {
            // left 中保存的是i之前所有数的乘积
            res[i] = res[i - 1] * nums[i - 1];
        }

        // 然后从后向前变量,通过变量 right保存前几位数的乘积
        int right = 1;
        for (int i = len - 1; i >= 0; i--) {
            res[i] *= right;
            // 放在返回值的后面,就相当于i + 1
            right *= nums[i];
        } 
        return res;
    }
}

时间复杂度: O(N),其中N指的是数组nums的大小。分析与方法一相同。
空间复杂度: O(1),输出数组不算进空间复杂度中,因此我们只需要常数的空间存放变量。

相关推荐
q***33371 小时前
oracle 12c查看执行过的sql及当前正在执行的sql
java·sql·oracle
mit6.8243 小时前
bfs|栈
算法
tobebetter95273 小时前
How to manage python versions on windows
开发语言·windows·python
Y***h1874 小时前
第二章 Spring中的Bean
java·后端·spring
9***P3344 小时前
PHP代码覆盖率
开发语言·php·代码覆盖率
8***29314 小时前
解决 Tomcat 跨域问题 - Tomcat 配置静态文件和 Java Web 服务(Spring MVC Springboot)同时允许跨域
java·前端·spring
CoderYanger4 小时前
优选算法-栈:67.基本计算器Ⅱ
java·开发语言·算法·leetcode·职场和发展·1024程序员节
jllllyuz5 小时前
Matlab实现基于Matrix Pencil算法实现声源信号角度和时间估计
开发语言·算法·matlab
q***06295 小时前
Tomcat的升级
java·tomcat
夏鹏今天学习了吗5 小时前
【LeetCode热题100(72/100)】前 K 个高频元素
leetcode