题目
给你一个长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4]
输出: [24,12,8,6]
提示:题目数据保证数组之中任意元素的全部前缀元素和后缀(甚至是整个数组)的乘积都在 32 位整数范围内。
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
进阶: 你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)。
解法
拿到题目首先的想法是:两次for循环,一次乘积一次做除法。但是后来发现说明中注明不要使用除法,便只能向其他方法。
既然是算除了自己之外的累乘,便可以以当前所在位置为分割点,分别计算左侧元素乘积 和 右侧元素乘积,之后再进行相乘。
对此由以下解法:
算法一(摘自LeetCode官方解法):
初始化两个空数组 L 和 R。对于给定索引 i,L[i] 代表的是 i 左侧所有数字的乘积,R[i] 代表的是 i 右侧所有数字的乘积。
我们需要用两个循环来填充 L 和 R 数组的值。对于数组 L,L[0] 应该是 1,因为第一个元素的左边没有元素。对于其他元素:L[i] = L[i-1] * nums[i-1]。
同理,对于数组 R,R[length-1] 应为 1。length 指的是输入数组的大小。其他元素:R[i] = R[i+1] * nums[i+1]。
当 R 和 L 数组填充完成,我们只需要在输入数组上迭代,且索引 i 处的值为:L[i] * R[i]。
class Solution { public int[] productExceptSelf(int[] nums) { int arrLen = nums.length; int[] leftNums = new int[arrLen]; int[] rightNums = new int[arrLen]; leftNums[0] = 1;rightNums[arrLen-1] = 1; for(int i = 1; i < arrLen; i++){ leftNums[i] = leftNums[i-1] * nums[i-1]; rightNums[arrLen-i-1] = rightNums[arrLen-i] * nums[arrLen-i]; } for(int i = 0; i < arrLen; i++){ leftNums[i] *= rightNums[i]; } return leftNums; } }
复杂度分析
时间复杂度:O(N),其中 N 指的是数组 nums 的大小。预处理 L 和 R 数组以及最后的遍历计算都是 O(N) 的时间复杂度。
空间复杂度:O(N),其中 N 指的是数组 nums 的大小。使用了 L 和 R 数组去构造答案,L 和 R 数组的长度为数组 nums 的大小。
算法二:共享数组方式
整体思路和官方解题思路相同:左乘*右乘。
定义返回数组 returnNums 并将其看作共享数组,同时从左右两端填充数据;之后定义 left,right 来存储左右乘积并循环迭代更新。
在两指针交会前,只需对数组进行简单的填充即可;
在两者交互时(仅发生在奇数长度)其填充值为 left*right。
两者交汇后,数组的值应填入最终值:因为左侧部分已经存储了左乘积,而即将计算得到右乘积;右侧部分已存储了右乘积,即将获得左乘积。故直接相乘即可。returnNums[i] = left 和 returnNums[j] = right。
class Solution { public int[] productExceptSelf(int[] nums) { int arrLen = nums.length; int[] returnNums = new int[arrLen]; int left = 1, right = 1; // 临时存储 returnNums[0] = 1; returnNums[arrLen-1] = 1; for(int i = 1, j = arrLen-2; i < arrLen; i++, j--){ left *= nums[i-1]; right *= nums[j+1]; if(i < j){ // 两指针为交会 returnNums[i] = left; returnNums[j] = right; }else if(i == j){ // 两指针重合,奇数位情况下发生 returnNums[i] = left*right; }else{ // 两指针错位 returnNums[i] *= left; returnNums[j] *= right; } } return returnNums; } }
复杂度分析
时间复杂度: O(N),同上一解题方式相同,进行了一次长度为N的循环,其时间复杂度为O(N)。
空间复杂度:O(1),题目中所述,返回数组的空间不算,故所使用的额外存储空间为 left 和 right。故只有常数级别的空间复杂度。
以上是[LeetCode]238. 除自身以外数组的乘积解题思路的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Dreamweaver Mac版
视觉化网页开发工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

SublimeText3汉化版
中文版,非常好用