除自身以外数组的乘积 动态规划
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4]输出: [24,12,8,6]
提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
进阶:
你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
思路:
这道题用动态规划来做。
使用动态规划的话我们需要额外开辟数组,虽然题目中的进阶要求希望空间复杂度为常数级别,但前提也得是先知道动态规划方法,然后再在此基础上进行压缩,就可以实现常数级别的空间复杂度。这就像股票买卖问题一样,空间复杂度的降低来自于在先前方法基础上的优化,但本质都是相同的。
如何使用动态规划呢?题目要求不许用除法,所以我们求每一个数的“除自身以外的乘积”,就老老实实算它左边的乘积,和右边的乘积就好了。
所以我们用最好理解的办法:定义left_dp,和right_dp两个动态规划数组。left_dp[i]表示nums[i]这个数左边所有数的乘积;right_dp[i]则代表这个位置右边所有数的乘积。只要我们提前求出来这两个数组,那么就可以在只遍历一遍原数组的情况下求出各个位置“除自身以外的乘积”了。
状态转移方程也很简单,以left_dp为例,有:left_dp[i] = nums[i-1]*left_dp[i-1],根据dp数组的意思应该很好理解了:i位置前的乘积=i-1位置的值*i-1位置前的乘积。
代码:
class Solution(object):
def productExceptSelf(self, nums):
lenth = len(nums)#获得数组长度
left_dp = [0]*lenth#定义两个dp数组
right_dp = [0]*lenth
left_dp[0]=1#初始化,第1位左边的乘机为1
left_dp[1]=nums[0]#第2位左边的乘积为num[0]
for i in range(2,lenth):#开始写状态转移方程
left_dp[i] = nums[i-1]*left_dp[i-1]
#右边的同理
right_dp[-1]=1
right_dp[-2]=nums[-1]
for i in range(lenth-3,-1,-1):
right_dp[i] = nums[i+1]*right_dp[i+1]
res = [0]*lenth
#利用左右两边相乘得到最终结果
for i in range(lenth):
res[i] = left_dp[i]*right_dp[i]
return res
在此代码基础上可以去写优化方法,因为给的nums必然是占O(n)空间的,也正好可以利用这个数组进行操,从而实现额外空间复杂度到常数级别。不过优化后代码可读性和理解性就非常差了,想把代码贴出来的,但是发现注释都写不出来,就算了~
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了