【数据结构和算法】除自身以外数组的乘积

简介: 给你一个整数数组nums,返回数组answer,其中answer[i]等于nums中除nums[i]之外其余各元素的乘积。题目数据保证数组nums之中任意元素的全部前缀元素和后缀的乘积都在32 位整数范围内。请不要使用除法,且在O(n)时间复杂度内完成此题。

 其他系列文章导航

Java基础合集

数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

三、代码

四、复杂度分析


前言

这是力扣的238题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的两种。


一、题目描述

给你一个整数数组 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) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)


    二、题解

    思路与算法:

    本题的难点在于 不能使用除法 ,即需要 只用乘法 生成数组 ans 。根据题目对 ans[i] 的定义,可列出下图所示的表格。

    根据表格的主对角线(全为 1 ),可将表格分为 上三角 和 下三角 两部分。分别迭代计算下三角和上三角两部分的乘积,即可不使用除法就获得结果。

    下图中 A=nums , B=ans。

    image.gif编辑

    流程:

      1. 初始化:数组 ans ,其中 ans[0]=1 ;辅助变量 tmp=1 。
      2. 计算 ans[i] 的 下三角 各元素的乘积,直接乘入 ans[i] 。
      3. 计算 ans[i] 的 上三角 各元素的乘积,记为 tmp ,并乘入 ans[i] 。
      4. 返回 ans 。

      补充:

      见下图就知道了:

      原数组:       [1       2       3       4]
      左部分的乘积:   1       1      1*2    1*2*3
      右部分的乘积: 2*3*4    3*4      4      1
      结果:        1*2*3*4  1*3*4   1*2*4  1*2*3*1

      image.gif

      从上面的图可以看出,当前位置的结果就是它左部分的乘积再乘以它右部分的乘积。因此需要进行两次遍历,第一次遍历用于求左部分的乘积,第二次遍历在求右部分的乘积的同时,再将最后的计算结果一起求出来。


      三、代码

      Java版本:

      class Solution {
          public int[] productExceptSelf(int[] nums) {
              int len = nums.length;
              if (len == 0) return new int[0];
              int[] ans = new int[len];
              ans[0] = 1;
              int tmp = 1;
              for (int i = 1; i < len; i++) {
                  ans[i] = ans[i - 1] * nums[i - 1];
              }
              for (int i = len - 2; i >= 0; i--) {
                  tmp *= nums[i + 1];
                  ans[i] *= tmp;
              }
              return ans;
          }
      }

      image.gif

      C++版本:

      class Solution {
      public:
          vector<int> productExceptSelf(vector<int>& nums) {
              int len = nums.size();
              if (len == 0) return vector<int>();
              vector<int> ans(len);
              ans[0] = 1;
              int tmp = 1;
              for (int i = 1; i < len; i++) {
                  ans[i] = ans[i - 1] * nums[i - 1];
              }
              for (int i = len - 2; i >= 0; i--) {
                  tmp *= nums[i + 1];
                  ans[i] *= tmp;
              }
              return ans;
          }
      };

      image.gif

      Python版本:

      class Solution:
          def productExceptSelf(self, nums: List[int]) -> List[int]:
              length = len(nums)
              if length == 0:
                  return []
              ans = [1] * length
              tmp = 1
              for i in range(1, length):
                  ans[i] = ans[i - 1] * nums[i - 1]
              for i in range(length - 2, -1, -1):
                  tmp *= nums[i + 1]
                  ans[i] *= tmp
              return ans

      image.gif


      四、复杂度分析

        • 时间复杂度 O(N) : 其中 N 为数组长度,两轮遍历数组 nums ,使用 O(N) 时间。
        • 空间复杂度 O(1) : 变量 tmp 使用常数大小额外空间(数组 ans 作为返回值,不计入复杂度考虑)。


        目录
        相关文章
        |
        1月前
        |
        存储 人工智能 算法
        数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
        这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
        70 3
        数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
        |
        1月前
        |
        机器学习/深度学习 存储 缓存
        数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
        文章主要介绍了排序算法的分类、时间复杂度的概念和计算方法,以及常见的时间复杂度级别,并简单提及了空间复杂度。
        26 1
        数据结构与算法学习十:排序算法介绍、时间频度、时间复杂度、常用时间复杂度介绍
        |
        1月前
        |
        算法 程序员 索引
        数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
        栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
        31 1
        数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
        |
        1月前
        |
        存储 算法 Java
        Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
        Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
        33 4
        |
        1月前
        |
        搜索推荐 算法
        数据结构与算法学习十四:常用排序算法总结和对比
        关于常用排序算法的总结和对比,包括稳定性、内排序、外排序、时间复杂度和空间复杂度等术语的解释。
        20 0
        数据结构与算法学习十四:常用排序算法总结和对比
        |
        1月前
        |
        机器学习/深度学习 搜索推荐 算法
        探索数据结构:初入算法之经典排序算法
        探索数据结构:初入算法之经典排序算法
        |
        1月前
        |
        算法 Java 索引
        数据结构与算法学习十五:常用查找算法介绍,线性排序、二分查找(折半查找)算法、差值查找算法、斐波那契(黄金分割法)查找算法
        四种常用的查找算法:顺序查找、二分查找(折半查找)、插值查找和斐波那契查找,并提供了Java语言的实现代码和测试结果。
        21 0
        |
        30天前
        |
        算法 安全 数据安全/隐私保护
        基于game-based算法的动态频谱访问matlab仿真
        本算法展示了在认知无线电网络中,通过游戏理论优化动态频谱访问,提高频谱利用率和物理层安全性。程序运行效果包括负载因子、传输功率、信噪比对用户效用和保密率的影响分析。软件版本:Matlab 2022a。完整代码包含详细中文注释和操作视频。
        |
        7天前
        |
        算法 数据安全/隐私保护 索引
        OFDM系统PAPR算法的MATLAB仿真,对比SLM,PTS以及CAF,对比不同傅里叶变换长度
        本项目展示了在MATLAB 2022a环境下,通过选择映射(SLM)与相位截断星座图(PTS)技术有效降低OFDM系统中PAPR的算法实现。包括无水印的算法运行效果预览、核心程序及详尽的中文注释,附带操作步骤视频,适合研究与教学使用。
        |
        15天前
        |
        算法 数据挖掘 数据安全/隐私保护
        基于FCM模糊聚类算法的图像分割matlab仿真
        本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。

        热门文章

        最新文章