当前位置: 首页 > backend >正文

LeetCode 238:除自身以外数组的乘积(Java实现)

文章目录

    • **题目描述**
    • 解决思路
      • 1. 两次遍历法(左右乘积法)
      • 2. 核心思想
    • Java代码实现
    • 复杂度分析
    • 示例说明
      • 步骤分解
    • 注意事项
    • 总结

题目描述

给定一个整数数组 nums,返回一个数组 answer,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。题目要求:

  1. 时间复杂度为 O(n)
  2. 不能使用除法
  3. 空间复杂度为 O(1)(不包含输出数组)

解决思路

由于不能使用除法,直接计算每个位置左右两侧的乘积是一种高效的方法。具体步骤如下:

1. 两次遍历法(左右乘积法)

  • 第一次遍历(左→右):计算每个元素左侧所有元素的乘积,并存储在结果数组 answer 中。
  • 第二次遍历(右→左):维护一个变量 rightProduct,动态计算当前元素右侧所有元素的乘积,并与左侧乘积相乘,得到最终结果。

2. 核心思想

  • 空间优化:直接复用结果数组 answer,避免额外空间。
  • 分治思想:将问题拆解为“左侧乘积”和“右侧乘积”两部分,分别求解后合并。

Java代码实现

class Solution {public int[] productExceptSelf(int[] nums) {int n = nums.length;int[] answer = new int[n];// 1. 计算左侧乘积(answer[i] = nums[0] * nums[1] * ... * nums[i-1])answer[0] = 1; // 第一个元素左侧无元素,初始化为1for (int i = 1; i < n; i++) {answer[i] = answer[i - 1] * nums[i - 1];}// 2. 计算右侧乘积并合并结果int rightProduct = 1; // 最后一个元素右侧无元素,初始化为1for (int i = n - 1; i >= 0; i--) {answer[i] *= rightProduct; // 左侧乘积 * 右侧乘积rightProduct *= nums[i];     // 更新右侧乘积}return answer;}
}

复杂度分析

  • 时间复杂度:O(n),两次独立遍历数组。
  • 空间复杂度:O(1),仅使用常量额外空间(输出数组不计入复杂度)。

示例说明

以输入 nums = [1, 2, 3, 4] 为例:

步骤分解

  1. 左侧乘积计算

    • answer[0] = 1(左侧无元素)
    • answer[1] = answer[0] * nums[0] = 1 * 1 = 1
    • answer[2] = answer[1] * nums[1] = 1 * 2 = 2
    • answer[3] = answer[2] * nums[2] = 2 * 3 = 6
    • 此时 answer = [1, 1, 2, 6]
  2. 右侧乘积计算与合并

    • 初始化 rightProduct = 1
    • i=3answer[3] *= 16*1=6,更新 rightProduct = 1*4=4
    • i=2answer[2] *= 42*4=8,更新 rightProduct = 4*3=12
    • i=1answer[1] *= 121*12=12,更新 rightProduct = 12*2=24
    • i=0answer[0] *= 241*24=24,更新 rightProduct = 24*1=24
    • 最终结果:answer = [24, 12, 8, 6]

注意事项

  • 边界条件:当输入数组长度为1时,直接返回 [1]
  • 避免溢出:题目未明确说明数据范围,但实际应用中需考虑乘积溢出问题。

总结

通过两次遍历分别计算左右两侧的乘积,既避免了除法,又优化了空间复杂度。该方法适用于需要前后缀计算的场景(如“接雨水”问题)。关键在于分步拆解问题,复用结果数组减少空间占用。

http://www.xdnf.cn/news/4094.html

相关文章:

  • CRM客户关系管理系统高级版客户管理销售管理合同管理数据分析TP6.0框架源码
  • 阿里云服务器深度科普:技术架构与未来图景
  • kdump详解
  • 基于SRS实现流媒体服务器(最简单的流媒体服务器)
  • 【外围电路】0.介绍
  • react路由使用方法
  • 【ArUco boards】标定板检测
  • 《架构安全原则》解锁架构安全新密码
  • c++进阶——AVL树主要功能的模拟实现(附带旋转操作讲解)
  • ADK 第四篇 Runner 执行器
  • 把Android设备变成“国标摄像头”:GB28181移动终端实战接入指南
  • 博图V20编译报错:备不受支持,无法编译。请更改为受支持的设备。
  • C++初学者的入门指南
  • [Windows] 批量修改文件/文件夹时间戳工具 NewFileTime 7.71
  • VUE3报错 ReferenceError: Cannot access ‘openInit‘ before initialization
  • 【Qt】配置环境变量
  • educoder平台课-Python程序设计-8.文件
  • 价格识别策略思路
  • 第16章 监控和排除日志记录错误
  • 牛客 Wall Builder II 题解
  • Redis 数据类型详解(二):Hash 类型全解析
  • 数据结构-希尔排序(Python)
  • 立夏三候:蝼蝈鸣,蚯蚓出,王瓜生
  • 【AI学习】DeepSeek-R1是如何训练的?
  • Kdump 收集器及使用方式
  • archlinux安装waydroid
  • 查看并升级Docker里面Jenkins的Java17到21版本
  • 双目测量中的将视差图重投影成三维坐标图
  • 某信服EDR3.5.30.ISO安装测试(二)
  • kotlin 03flow-stateFlow和sharedFlow企业中使用