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

力扣经典算法篇-11-除自身以外数组的乘积(总乘积求除法,左右乘积法)

1、题干

给你一个整数数组 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
输入 保证 数组 answer[i] 在 32 位 整数范围内

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

2、解题

方法一:暴力求解法

定义额外的数组依次遍历进行赋值,遇到相同下标时跳过。

public static int[] productExceptSelf(int[] nums) {
        int[] result = new int[nums.length];
        int temp;
        for (int i = 0; i < nums.length; i++) {
            temp = 1;
            for (int j = 0; j < nums.length; j++) {
                if (j == i) {
                    continue;
                }
                temp = temp * nums[j];
                if (temp == 0) {
                    break;
                }
            }
            result[i] = temp;
        }
        return result;
    }

方法二:总乘积求除法

先求出所有元素的乘积,之后除以当前元素值就是其余元素的乘积值。

注意:值为0的元素造成干扰,所以需要预先判断元素为0的数量和非0元素的乘积。
大于1时,结果必定都是0。
等于1时,元素值为0时,为非0元素的乘积;不为0时,都是0。
小于0时,即没有0值的元素,直接用总乘积除以当前元素获取。

public static int[] productExceptSelf(int[] nums) {
        int[] result = new int[nums.length];

        List<Integer> zeroList = new ArrayList<>();
        int all = 1;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] == 0) {
                zeroList.add(i);
            } else {
                all *= nums[i];
            }
        }
        if (zeroList.size() > 1) {
            return result;
        } else if (zeroList.size() == 1) {
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] == 0) {
                    result[i] = all;
                } else {
                    result[i] = 0;
                }
            }
        } else {
            for (int i = 0; i < nums.length; i++) {
                result[i] = all / nums[i];
            }
        }

        return result;
    }

方法三:左右乘积法

定义两个额外的数组,左数组和右数组。
左数组保存从左遍历,从头开始到前一个元素的结果。右数组则保存从右遍历,元素的乘积。
具体解释:
左数组:

  • 计算第0个元素,左边没有元素,默认1;
  • 计算第1个元素,左边只有1个元素,为原始数组第0个元素的值;
  • 计算第2个元素,左边包含第0和第1个两个元素,为这两个元素的乘积,之后以此类推

右数组和左数组同理,方向相反。

   public static int[] productExceptSelf(int[] nums) {
        int[] result = new int[nums.length];

        int[] left = new int[nums.length];      // 从左遍历,存储每个元素左边元素的乘积
        int[] right = new int[nums.length];       // 从右遍历,存储每个元素右边元素的乘积

        // 因为第0个元素左边没有元素,默认1。第1个元素,则为第0个元素的值,第2个元素为第0和第1个元素的乘积,以此类推
        left[0] = 1;
        for (int i = 1; i < nums.length; i++) {
            left[i] = left[i - 1] * nums[i - 1];
        }
		
		// 右数组
        right[nums.length - 1] = 1;
        for (int i = nums.length - 2; i >= 0; i--) {
            right[i] = right[i + 1] * nums[i + 1];
        }

        // 结果数组
        for (int i = 0; i < nums.length; i++) {
            result[i] = left[i] * right[i];
        }

        return result;
    }

方法四:左右乘积法优化

方法三的优化,左数组同理生成,右数组在遍历生成的同时就可以计算结果元素,并保存到结果中。

 public static int[] productExceptSelf(int[] nums) {
        int[] left = new int[nums.length];      // 从左遍历,存储每个元素左边元素的乘积

        // 因为第0个元素左边没有元素,默认1。第1个元素,则为第0个元素的值,第2个元素为第0和第1个元素的乘积,以此类推
        left[0] = 1;
        for (int i = 1; i < nums.length; i++) {
            left[i] = left[i - 1] * nums[i - 1];
        }

        int right = 1;
        for (int i = nums.length - 1; i >= 0; i--) {
            left[i] = left[i] * right;
            right = right * nums[i];
        }

        return left;
    }

逆风翻盘,Dare To Be!!!


文章转载自:
http://acolyte.tmizpp.cn
http://balefully.tmizpp.cn
http://centreless.tmizpp.cn
http://centripetalism.tmizpp.cn
http://barware.tmizpp.cn
http://amianthus.tmizpp.cn
http://arrogate.tmizpp.cn
http://atropos.tmizpp.cn
http://adiabat.tmizpp.cn
http://carrageenan.tmizpp.cn
http://chevroler.tmizpp.cn
http://burra.tmizpp.cn
http://americanophobia.tmizpp.cn
http://armory.tmizpp.cn
http://audiphone.tmizpp.cn
http://castellany.tmizpp.cn
http://beetleheaded.tmizpp.cn
http://ackey.tmizpp.cn
http://averment.tmizpp.cn
http://carecloth.tmizpp.cn
http://apache.tmizpp.cn
http://adjudicative.tmizpp.cn
http://carmelite.tmizpp.cn
http://barf.tmizpp.cn
http://bakeshop.tmizpp.cn
http://ceraceous.tmizpp.cn
http://cashmere.tmizpp.cn
http://ablaze.tmizpp.cn
http://chordee.tmizpp.cn
http://achinese.tmizpp.cn
http://www.dtcms.com/a/126332.html

相关文章:

  • 探索 C++ 中的 const 关键字
  • 美食推荐小程序
  • OpenFeign 的实现原理详解
  • 探索在视频深度伪造中的细微的表情变化或对特定面部特征的小改动检测方法
  • 使用numpy构建逻辑回归模型及训练流程
  • 关于哈希冲突的讨论
  • TDOA定位算法核心优势解析(2025年更新)
  • 【Java面试系列】Spring Cloud微服务架构中的分布式事务实现与性能优化详解 - 3-5年Java开发必备知识
  • netty中的ChannelHandler详解
  • 【DB2】备份失败SQL1762N
  • python相关面试题
  • 算法系列——无监督学习——15.混合高斯分布
  • 光学工程考研调剂推荐
  • c++将jpg转换为灰度图
  • APCC:CloudberryDB和Greenplum数据库的管理利器
  • LLM_基于OpenAI的极简RAG
  • Django从零搭建卖家中心注册页面实战
  • 什么是 ForkJoinPool
  • 针对deepseek的核心论文写作提示词模板(适用于SCI论文、CCF会议论文、北大核心论文、南大核心论文)
  • JavaSE反射机制干货
  • CloudFlare Page 如何和 GitHub 创建连接
  • go游戏后端开发34:补杠功能与到时出牌
  • BERT - 今日头条新闻分类任务实战
  • 软件测试岗位:IT行业中的质量守护者
  • AI预测3D新模型百十个定位预测+胆码预测+去和尾2025年4月11日第49弹
  • STM32+EC600E 4G模块 与华为云平台通信
  • 多因素认证
  • P1439 【模板】最长公共子序列
  • STM32 模块化开发指南 · 第 4 篇 用状态机管理 BLE 应用逻辑:分层解耦的实践方式
  • poi-tl