Python算法题集_除自身以外数组的乘积

news2024/10/7 16:22:53

 Python算法题集_除自身以外数组的乘积

  • 题239:除自身以外数组的乘积
  • 1. 示例说明
  • 2. 题目解析
    • - 题意分解
    • - 优化思路
    • - 测量工具
  • 3. 代码展开
    • 1) 标准求解【暴力求解】
    • 2) 改进版一【字典改进乘积计算】
    • 3) 改进版二【字典改进乘积计算+预计算数字乘积】
    • 4) 改进版三【前缀乘积+后缀乘积】
    • 5) 改进版四【前缀乘积+后缀乘积+一次性分配内存】
    • 6) 改进版五【改进空间复杂度】
  • 4. 最优算法

本文为Python算法题集之一的代码示例

题239:除自身以外数组的乘积

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
  • 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内
  • 进阶: 你可以在 O(1) 的额外空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组 不被视为 额外空间。)

2. 题目解析

- 题意分解

  1. 本题为求所有子数组的乘积
  2. 本题的主要计算有2处,1是子数组遍历,2是子数组求乘积
  3. 基本的办法是双层循环,挨个计算,所以基本的时间算法复杂度为O(n2)

- 优化思路

  1. 减少循环层次

  2. 增加分支,减少计算集

  3. 采用内置算法来提升计算速度

  4. 分析题目特点,分析最优解

    1)采用字典存储数组中每个数字的数量,可以加快子数组求乘积的速度

    2)将字典中每个数字的乘积、少乘一次的乘积先计算出来,改计算为字典查询,可以加快子数组求乘积的速度

    3)采用类似前缀和的思路,计算前缀乘积、后缀乘积,这样第i个元素的除自身外数组的乘积=前缀乘积i-1 * 后缀乘积i+1,可以减少循环层次

    4)进阶算法要求少用临时空间,使用结果数组和原始数组,可以配合完成结果计算


- 测量工具

  • 本地化测试说明:LeetCode网站测试运行时数据波动很大,因此需要本地化测试解决这个问题
  • CheckFuncPerf(函数用时和内存占用测试模块)已上传到CSDN,地址在这里:Python算法题集_检测函数用时和内存占用的模块
  • 测试的超时测试用例文件是官网的,已上传到CSDN,地址在这里:力扣算法题:除自身以外数组的乘积,测试超时数组,长度5W

3. 代码展开

1) 标准求解【暴力求解】

双层循环,超时未过

import CheckFuncPerf as cfp

def productExceptSelf_base(nums):
 result = []
 for iIdx in range(len(nums)):
     imulti = 1
     for jIdx in range(len(nums)):
         if jIdx!= iIdx:
             imulti *= nums[jIdx]
     result.append(imulti)
 return result

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]
result = cfp.getTimeMemoryStr(productExceptSelf_ext1, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 productExceptSelf_base 的运行时间为 194010.75 ms;内存使用量为 2348.00 KB 执行结果 = 50000

2) 改进版一【字典改进乘积计算】

尴尬的双层循环 尴尬通过,超过5%在这里插入图片描述

import CheckFuncPerf as cfp

def productExceptSelf_ext1(nums):
 dic_nums = {}
 for iIdx in range(len(nums)):
     dic_nums[nums[iIdx]] = dic_nums.get(nums[iIdx], 0) + 1
 result = []
 for iIdx in range(len(nums)):
     imulti = 1
     for aKey in dic_nums.keys():
         if aKey != nums[iIdx]:
             imulti *= aKey ** dic_nums[aKey]
         else:
             imulti *= aKey ** (dic_nums[aKey]-1)
     result.append(imulti)
 return result

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]
result = cfp.getTimeMemoryStr(productExceptSelf_ext1, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 productExceptSelf_ext1 的运行时间为 90.02 ms;内存使用量为 1944.00 KB 执行结果 = 50000

3) 改进版二【字典改进乘积计算+预计算数字乘积】

改进版,然并卵,还是双层循环 微小改进,超过17%在这里插入图片描述

import CheckFuncPerf as cfp

def productExceptSelf_ext2(nums):
 dic_nums = {}
 for iIdx in range(len(nums)):
     dic_nums[nums[iIdx]] = dic_nums.get(nums[iIdx], [0, 1, 1])
     dic_nums[nums[iIdx]][0] += 1
 for aKey in dic_nums.keys():
     dic_nums[aKey][1] = int(aKey ** (dic_nums[aKey][0]-1))
     dic_nums[aKey][2] = int(aKey ** dic_nums[aKey][1])
 result = []
 for iIdx in range(len(nums)):
     imulti = 1
     for bKey in dic_nums.keys():
         if bKey != nums[iIdx]:
             imulti *= dic_nums[bKey][2]
         else:
             imulti *= dic_nums[bKey][1]
     result.append(imulti)
 return result

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]
result = cfp.getTimeMemoryStr(productExceptSelf_ext2, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 productExceptSelf_ext2 的运行时间为 46.00 ms;内存使用量为 924.00 KB 执行结果 = 50000

4) 改进版三【前缀乘积+后缀乘积】

不再是双层循环,指标改进显著 指标优异,超越94%在这里插入图片描述

import CheckFuncPerf as cfp

def productExceptSelf_ext3(nums):
 leftmultilist, rightmultilist = [1] * len(nums), [1] * len(nums)
 leftmulti, rightmulti = 1, 1
 for iIdx in range(len(nums)):
     leftmulti *= nums[iIdx]
     rightmulti *= nums[-iIdx-1]
     leftmultilist[iIdx] = leftmulti
     rightmultilist[-iIdx-1] = rightmulti
 result = [rightmultilist[1]]
 for iIdx in range(1, len(nums)-1):
     result.append(leftmultilist[iIdx-1]*rightmultilist[iIdx+1])
 result.append(leftmultilist[len(nums)-2])
 return result

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]
result = cfp.getTimeMemoryStr(productExceptSelf_ext3, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 productExceptSelf_ext3 的运行时间为 22.00 ms;内存使用量为 2332.00 KB 执行结果 = 50000

5) 改进版四【前缀乘积+后缀乘积+一次性分配内存】

直接分配结果集内存,不是一个元素一个元素的分配,实测有效 飞龙在天,超越97%在这里插入图片描述

import CheckFuncPerf as cfp

def productExceptSelf_ext4(nums):
 leftmultilist, rightmultilist, result = [1] * len(nums), [1] * len(nums), [1] * len(nums)
 leftmulti, rightmulti = 1, 1
 for iIdx in range(len(nums)):
     leftmulti *= nums[iIdx]
     rightmulti *= nums[-iIdx - 1]
     leftmultilist[iIdx] = leftmulti
     rightmultilist[-iIdx - 1] = rightmulti
 result[0] = rightmultilist[1]
 for iIdx in range(1, len(nums) - 1):
     result[iIdx] = leftmultilist[iIdx - 1] * rightmultilist[iIdx + 1]
 result[-1] = leftmultilist[len(nums) - 2]
 return result

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]
result = cfp.getTimeMemoryStr(productExceptSelf_ext4, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 productExceptSelf_ext4 的运行时间为 21.00 ms;内存使用量为 2252.00 KB 执行结果 = 50000

6) 改进版五【改进空间复杂度】

不使用前缀乘积和后缀乘积数组,使用传入数组和结果数组直接计算,节省了内存分配环节,是本文最优的算法

网站波动,虚伪的95%在这里插入图片描述

import CheckFuncPerf as cfp

def productExceptSelf_ext5(nums):
 result = [1] * len(nums)
 for iIdx in range(1, len(nums)):
     result[iIdx] = result[iIdx-1] * nums[iIdx-1]
 iright = 1
 for iIdx in range(1, len(nums)):
     iright *= nums[-iIdx]
     result[-iIdx-1] = result[-iIdx-1] * iright
 return result

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]
result = cfp.getTimeMemoryStr(productExceptSelf_ext5, nums)
print(result['msg'], '执行结果 = {}'.format(len(result['result'])))

# 运行结果
函数 productExceptSelf_ext5 的运行时间为 18.01 ms;内存使用量为 1856.00 KB 执行结果 = 50000

4. 最优算法

根据本地日志分析,最优算法为第6种productExceptSelf_ext5

testcase_big = open(r'testcase/hot16_big.txt', mode='r', encoding='utf-8').read().replace('[', '').replace(']', '')
testcase_big = testcase_big.split(',')
nums = [int(x) for x in testcase_big]

# 6种算法本地速度实测比较    ⇒   最优算法为第6种
函数 productExceptSelf_base 的运行时间为 194010.75 ms;内存使用量为 2348.00 KB 执行结果 = 50000
函数 productExceptSelf_ext1 的运行时间为 90.02 ms;内存使用量为 1944.00 KB 执行结果 = 50000
函数 productExceptSelf_ext2 的运行时间为 46.00 ms;内存使用量为 924.00 KB 执行结果 = 50000
函数 productExceptSelf_ext3 的运行时间为 22.00 ms;内存使用量为 2332.00 KB 执行结果 = 50000
函数 productExceptSelf_ext4 的运行时间为 21.00 ms;内存使用量为 2252.00 KB 执行结果 = 50000
函数 productExceptSelf_ext5 的运行时间为 18.01 ms;内存使用量为 1856.00 KB 执行结果 = 50000

一日练,一日功,一日不练十日空

may the odds be ever in your favor ~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1426202.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux------进程优先级与进程切换

目录 一、进程优先级 二、优先级与权限的区别 三、优先级的查看 四、进程优先级修改 五、进程切换 六、linux2.6内核调度队列与调度原理 一、进程优先级 首先我们得知道一个进程总是需要排队的&#xff0c;他一会在运行队列中排队等待运行&#xff0c;一会在设备的等待队…

Python之数据分析

【案例】 某公司有2份数据文件&#xff0c;现在需要对其进行数据分析&#xff0c;计算每日的销售额并以柱状图表的形式进行展现。 数据如下&#xff1a; 一月份数据&#xff1a; 二月份数据&#xff1a; 需求分析 根据题目要求我们要得到每日销售额&#xff0c;分析文本数据可以…

微服务-微服务Alibaba-Nacos 源码分析 (源码流程图)

客户端流程 客户端心跳与实例往服务端注册

vue动态修改侧边菜单栏宽度

1.添加可修改宽度的dom元素 <div style"background: #f5f7fa;padding: 20px 10px;"><label>菜单宽度 </label><el-input v-model"sideWidth" placeholder"请输入宽度值" style"width: 100px"/> px<el-but…

2023爱分析·数据智能厂商全景报告|爱分析报告

利用多种数据智能技术实现数据驱动的分析与决策&#xff0c;已经成为当前企业数字化转型最重要的目标之一。随着数据来源日益丰富、数据体量快速增长&#xff0c;企业对数据的依赖和挖掘愈发深入&#xff0c;不仅带来数据应用场景、数据用户角色的复杂和多元&#xff0c;也使得…

TOP100 链表(上)

1.160. 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 图示两个链表在节点 c1 开始相交&#xff1a; 题目数据 保证 整个链式结构中不存在环。 注意&#xff0…

机器学习基础、数学统计学概念、模型基础技术名词及相关代码个人举例

1.机器学习基础 &#xff08;1&#xff09;机器学习概述 机器学习是一种人工智能&#xff08;AI&#xff09;的分支&#xff0c;通过使用统计学和计算机科学的技术&#xff0c;使计算机能够从数据中学习并自动改进性能&#xff0c;而无需进行明确的编程。它涉及构建和训练机器…

助力水下潜行:浮力调节系统仿真

01.建设海洋强国 海洋蕴藏着丰富的资源&#xff0c;二十大报告强调&#xff0c;要“发展海洋经济&#xff0c;保护海洋生态环境&#xff0c;加快建设海洋强国”。建设海洋强国旨在通过科技创新驱动、合理开发利用海洋资源、强化海洋环境保护与生态修复、提升海洋经济质量等多个…

6个在线网页原型工具的推荐选择

即时设计 即时设计可以说为中国设计师提供了很大的帮助。作为最受欢迎的在线网页原型图设计协作工具之一&#xff0c;在线协作是其核心特征。在线协作工作允许整个团队同时编辑文件&#xff0c;并可以随时随地访问。 团队共享组件库&#xff0c;使成员可以自由上传、下载和使用…

Git解决分支合并冲突的问题:分支合并提交出现了不同分支同一个文件的修改的冲突解决

有些时候我们合并分支的时候&#xff0c;会出现冲突&#xff0c;原因就是我们修改了分支A 的第一行代码&#xff0c;我们还修改了主分支上面同一个文件中的第一行代码&#xff08;分支A已经提交过一次&#xff09;&#xff0c;此时我们在次合并的时候就会出现冲突&#xff0c;需…

flowable 设置自定义属性教程

概述 由于工作需要给flowable工作流设计器添加自定义属性&#xff0c;以满足功能实现。所以这篇文章介绍下用flowable 开源的的flowable-ui 前端添加自定义属性&#xff0c;后端解析属性值的例子。 技术栈 序号技术点名称版本1Flowable6.8.0 使用的是flowable6.8.0 版的代码…

简述MinewSemi的GNSS模块引领体育与健康科技革新

体育与健康科技领域的创新一直在推动人们更健康、更活跃的生活方式。创新微公司的GNSS模块正成为这一变革的关键推动力。本文将深入研究MinewSemi的GNSS模块在体育和健康追踪领域的创新应用&#xff0c;探讨其如何帮助个体更全面地了解和改善自己的身体状态。 1. 个性化运动轨迹…

源码梳理(2)SpringMVC的执行流程及涉及到的相关组件

文章目录 1&#xff0c;Spring MVC核心组件DispatcherServlet1.1 DispatcherServlet的继承关系1.2 DispatcherServlet的doDispatch方法 2&#xff0c;核心组件HandlerMapping&#xff08;处理器映射器&#xff09;3&#xff0c;核心组件HandlerAdapter&#xff08;处理器适配器…

iOS pod sdk开发到发布,记录

本文章记录从开发sdk到发布cocopod的问题和流程,省的每次都忘还得重新查 1:pod lib create (sdk名称) 命令创建 工程结构,然后根据命令行提示进行选择. What platform do you want to use?? [ iOS / macOS ]。~》 iOS What language do you want to use?? [ Swift / Obj…

Jmeter高级使用

文章目录 JMeter之计数器JMeter之集合点JMeter之断言JMeter之动态关联后置处理器&#xff1a;正则表达式提取器 JMeter之分布式测试JMeter之组件执行顺序元件的作用域元件的执行顺序配置元件Http Cookie管理器 多协议接口的性能测试Debug采样器Http请求中文乱码的解决Post参数设…

循环神经网络RNN专题(01/6)

一、说明 RNN用于处理序列数据。在传统的神经网络模型中&#xff0c;是从输入层到隐含层再到输出层&#xff0c;层与层之间是全连接的&#xff0c;每层之间的节点是无连接的。但是这种普通的神经网络对于很多问题却无能无力。例如&#xff0c;你要预测句子的下一个单词是什么&a…

Netty如何解决粘包以及半包问题,以及目前最常用的LengthFieldBasedFrameDecoder

粘包&#xff08;Sticky Packets&#xff09;和半包&#xff08;Half Packets&#xff09; 粘包&#xff08;Sticky Packets&#xff09;和半包&#xff08;Half Packets&#xff09;是在网络通信中常见的两种问题&#xff0c;特别是在基于流的传输协议&#xff08;如TCP&…

基于tidevice实现iOS app自动化使用详解

目录 1、IOS自动化工具概述 2、tidevice工具的原理和使用 2.1、tidevice的原理 2.2、tidevice实现的功能 2.3、tidevice的安装 2.4、tidevice的使用 2.4.1、设备管理 1、查看已连接的设备的列表 2、检测设备连接状态 3、等待设备连接&#xff0c;只要有就连接就结束监…

《区块链简易速速上手小册》第9章:区块链的法律与监管(2024 最新版)

文章目录 9.1 法律框架和挑战9.1.1 基础知识9.1.2 主要案例&#xff1a;加密货币的监管9.1.3 拓展案例 1&#xff1a;跨国数据隐私和合规性9.1.4 拓展案例 2&#xff1a;智能合约的法律挑战 9.2 区块链的合规性问题9.2.1 基础知识9.2.2 主要案例&#xff1a;加密货币交易所的合…

【读点论文】A Survey of Deep Learning Approaches for OCR and Document Understanding

A Survey of Deep Learning Approaches for OCR and Document Understanding Abstract 文档是许多领域(如法律、金融和技术等)中许多业务的核心部分。自动理解发票、合同和简历等文件是有利可图的&#xff0c;开辟了许多新的商业途径。通过深度学习的发展&#xff0c;自然语言…