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

 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 cfpdef productExceptSelf_base(nums):result = []for iIdx in range(len(nums)):imulti = 1for jIdx in range(len(nums)):if jIdx!= iIdx:imulti *= nums[jIdx]result.append(imulti)return resulttestcase_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 cfpdef productExceptSelf_ext1(nums):dic_nums = {}for iIdx in range(len(nums)):dic_nums[nums[iIdx]] = dic_nums.get(nums[iIdx], 0) + 1result = []for iIdx in range(len(nums)):imulti = 1for 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 resulttestcase_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 cfpdef 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] += 1for 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 = 1for bKey in dic_nums.keys():if bKey != nums[iIdx]:imulti *= dic_nums[bKey][2]else:imulti *= dic_nums[bKey][1]result.append(imulti)return resulttestcase_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 cfpdef productExceptSelf_ext3(nums):leftmultilist, rightmultilist = [1] * len(nums), [1] * len(nums)leftmulti, rightmulti = 1, 1for iIdx in range(len(nums)):leftmulti *= nums[iIdx]rightmulti *= nums[-iIdx-1]leftmultilist[iIdx] = leftmultirightmultilist[-iIdx-1] = rightmultiresult = [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 resulttestcase_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 cfpdef productExceptSelf_ext4(nums):leftmultilist, rightmultilist, result = [1] * len(nums), [1] * len(nums), [1] * len(nums)leftmulti, rightmulti = 1, 1for iIdx in range(len(nums)):leftmulti *= nums[iIdx]rightmulti *= nums[-iIdx - 1]leftmultilist[iIdx] = leftmultirightmultilist[-iIdx - 1] = rightmultiresult[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 resulttestcase_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 cfpdef productExceptSelf_ext5(nums):result = [1] * len(nums)for iIdx in range(1, len(nums)):result[iIdx] = result[iIdx-1] * nums[iIdx-1]iright = 1for iIdx in range(1, len(nums)):iright *= nums[-iIdx]result[-iIdx-1] = result[-iIdx-1] * irightreturn resulttestcase_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.mzph.cn/news/661191.shtml

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

相关文章

第二集《修道宗范》

请大家打开讲义第5页&#xff0c;我们讲到丙一、先修出离心。 身为一个有情众生&#xff0c;我们内心当中&#xff0c;有一个没办法改变的本性&#xff0c;我们就是希望生命能够离苦得乐&#xff0c;这是没办法改变的。换句话说&#xff0c;我们每一个人都喜欢安乐&#xff0c…

Java技术栈 —— Hadoop入门(二)实战

Java技术栈 —— Hadoop入门&#xff08;二&#xff09; 一、用MapReduce对统计单词个数1.1 项目流程1.2 可能遇到的问题1.3 代码勘误1.4 总结 一、用MapReduce对统计单词个数 1.1 项目流程 (1) 上传jar包。 (2) 上传words.txt文件。 (3) 用hadoop执行jar包的代码&#xff0c;…

【C++】 C++入门 — auto关键字

C入门 auto 关键字1 介绍2 使用细则3 注意事项 Thanks♪(&#xff65;ω&#xff65;)&#xff89;谢谢阅读下一篇文章见&#xff01;&#xff01;&#xff01; auto 关键字 1 介绍 编程时常常需要把表达式的值赋给变量&#xff0c;这就要求在声明变量时清楚地知道表达式的类…

指针的深入理解(四)

这节主要讨论sizeof和strlen的区别&#xff0c;以及一些理解题。 sizeof 求的是对象的大小&#xff0c;深入理解一点就是&#xff1a;这个对象&#xff0c;他一定有一块对应的内存空间。求的就是这一块内存空间。 strlen 只能用来求字符串&#xff0c; 求取的是字符串的长度。…

面试了字节大模型算法岗(实习),快被问哭了。。。。

最近技术群组织了一次算法面试讨论会&#xff0c;今天分享的是一位小伙子的痛苦面试经历&#xff0c;如果你想加入我们的讨论群&#xff0c;见文末。 本次分享的内容如下&#xff1a; 应聘岗位&#xff1a;字节大模型算法实习生 面试轮数&#xff1a;第一轮 整体面试感觉&…

python封装的.exe文件是如何在cmd中获取.xml路径的?

这段日子搞项目算法封装&#xff0c;愁死我。来回改了三遍&#xff0c;总算把相对路径、绝对路径&#xff0c;还有cmd给.exe传参的方式搞懂了。 主要是这个语句 workspace sys.argv[1] sys.argv[]的作用就是,在运行python文件的时候从外部输入参数往文件里面传递参数。 外部就…

CTF盲水印工具:Blind-WaterMark安装

工具下载地址&#xff1a;GitCode - 开发者的代码家园 下载完毕后&#xff0c;只留这些东西就行 接下来需要安装两个依赖&#xff1a; opencv、matplotlib 直接pip install安装的话&#xff0c;工具使用会报错 所以需要到网站里挑选适合的版本进行安装 下载地址&#xff1…

项目:博客

1. 运行环境&#xff1a; 主机 主机名 系统 服务 192.168.223.129 Server_Web Linux Web 192.168.48.131 Server-NFS-DNS Linux NFS/DNS 2. 基础配置 配置主机名&#xff0c;静态IP地址 开启防火墙并配置 部分开启SElinux并配置 服务器之间使用同ntp.aliyun.com进行…

详讲api网关之kong的基本概念及安装和使用(二)

consul的服务注册与发现 如果不知道consul的使用&#xff0c;可以点击上方链接&#xff0c;这是我写的关于consul的一篇文档。 upstreamconsul实现负载均衡 我们知道&#xff0c;配置upstream可以实现负载均衡&#xff0c;而consul实现了服务注册与发现&#xff0c;那么接下来…

leetcode209长度最小的子数组|滑动窗口算法详细讲解学习

滑动窗口是一种基于双指针的一种思想&#xff0c;两个指针指向的元素之间形成一个窗口。 分类&#xff1a;窗口有两类&#xff0c;一种是固定大小类的窗口&#xff0c;一类是大小动态变化的窗口。 简而言之&#xff0c;滑动窗口算法在一个特定大小的字符串或数组上进行操作&…

DevEco Studio 保存自动格式化代码

目标&#xff1a;保存后自动格式化代码 单次快捷键&#xff1a;Ctrl Alt L 步骤一 步骤二

7.2、子集求和问题与背包密码系统

7.2、子集求和问题与背包密码系统 一、数学描述 1.1、第一种描述 20 世纪 70 年代末&#xff0c;默克尔和赫尔曼首次尝试将密码系统建立在一个 NP-完全问题上。他们使用了以下数学问题的一个版本&#xff0c;该问题是对经典knapsack问题的概括。 子集和问题 假设你有一个正…

【Midjourney】AI绘画案例(1)龙年吉祥神兽

说明&#xff1a; 1、文中图片版权均为Midjourney所有&#xff0c;请勿用作商业用途。 2、文中图片均经过 Upscale x 4 处理。 3、由于模型原因&#xff0c;某些图片存在暇玼。 1、吉祥神兽——天马&#xff08;独角兽&#xff09; 天马消灾星。 提示词 Prompt: Sky Unicor…

2023强网杯复现

强网先锋 SpeedUp 要求2的27次方的阶乘的逐位之和 在A244060 - OEIS 然后我们将4495662081进行sha256加密 就得到了flag flag{bbdee5c548fddfc76617c562952a3a3b03d423985c095521a8661d248fad3797} MISC easyfuzz 通过尝试输入字符串判断该程序对输入字符的验证规则为9…

Prometheus+grafana配置监控系统

使用docker compose安装 方便拓展, 配置信息都放在在 /docker/prometheus 目录下 1.目录结构如下 . ├── conf │ └── prometheus.yml ├── grafana_data ├── prometheus_data └── prometheus_grafana.yaml2.创建目录文件 mkdir /docker/prometheus &&am…

【unity小技巧】FPS简单的射击换挡瞄准动画控制

文章目录 射击动画控制换弹动画瞄准动画完结 射击动画控制 换弹动画 调用 瞄准动画 问题&#xff1a;瞄准时&#xff0c;但是动画会卡住&#xff0c;不会播放瞄准的待机动画 修改 调用 动画如果太快可以去修改播放速度 播放速度变慢了&#xff0c;可能导致切换待机动画也…

【PyQt】01-PyQt下载

文章目录 前言静态库 一、PyQt是什么&#xff1f;二、安装1.Windows环境下安装安装PyQt5Designer 2.Liunx环境下安装 总结 前言 拜吾师 PyQt5 快速入门 静态库 补充一点知识&#xff1a; Windows&#xff1a; .lib Linux: .a .so(动态库) 简单描述PyQt就是python调用C的Qt文…

《区块链简易速速上手小册》第4章:区块链与加密货币(2024 最新版)

文章目录 4.1 比特币与区块链4.1.1 比特币基础4.1.2 比特币交易的工作流程&#xff1a;4.1.3 拓展案例 1&#xff1a;闪电网络4.1.4 拓展案例 2&#xff1a;比特币ATM 4.2 其他主要加密货币4.2.1 加密货币的多样性4.2.2 以太坊的案例4.2.3 拓展案例 1&#xff1a;非同质化代币&…

郑庆科老师字体正版商用官方授权,字觅网为您提供官方授权渠道

近日,字觅网宣布成为郑庆科老师字体的签约字体品牌,并提供了官方正版商用授权渠道。庆科字体以其独特的风格和设计备受欢迎,现在通过字觅网,用户可以轻松获取该字体的正版商用授权。 用户只需访问庆科字体官网,即可查看庆科字体的详细列表,并选择所需字体进行下载。 在字觅网…

Unity3d Shader篇(一)— 顶点漫反射着色器解析

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、顶点漫反射着色器是什么&#xff1f;1. 顶点漫反射着色器的工作原理 二、编写顶点漫反射着色器1. 定义属性2. 创建 SubShader3. 编写着色器程序段4. 完成顶…