[leetcode]238. 除自身以外数组的乘积
题目描述
给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。
示例:
输入: [1,2,3,4]
输出: [24,12,8,6]
说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。
进阶:
你可以在常数空间复杂度内完成这个题目吗?( 出于对空间复杂度分析的目的,输出数组不被视为额外空间。)
算法
题中明确要求不能使用除法,本可以使用O(n^2)的双for暴力循环求解,但又要求在 O(n) 时间复杂度内。这就需要开动下脑筋,先来分析一下输出是怎么的得到:
24 = 2 * 3* 4
12 = 1 * 3 *4
8 = 1 * 2 * 4
6 = 1 * 2 *3
记保存输出的向量为vec,长度为length。
显然vec[i]上需要填的值 = 前i个数累乘 * 后(length - i - 1)个数累乘
仔细一思考,这个好像可以和动态规划有些关联,毕竟涉及到前i个、后几个连乘这样的关系。现在还处在探索问题的阶段,将问题分为两部分思考,一个是从前往后走,一个是从后往前走,保存它们的累乘结果到2个数组中(先不考虑进阶部分要求的常数空间复杂度),观察这2个数组和我们最终的输出有什么关联。
从前往后
| nums | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| dp_forward | 1 | 1 | 2 | 6 |
if i > 0:
dp[i] = (nums[0]到nums[i-1]的累乘)
else:
dp[0] = 1
"""
dp数组的前后值有这么一个数学关系:
dp[i] = dp[i-1] * nums[i-1]
"""
从后往前
为了方便阅读与理解,将nums反转为{4,3,2,1}。套用上面得到的数学关系,可以很轻松的到下面的结果:
| nums | 4 | 3 | 2 | 1 |
|---|---|---|---|---|
| dp_backward | 1 | 4 | 12 | 24 |
将nums反转为正常顺序{1,2,3,4},表格变为:
| nums | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| dp_backward | 24 | 12 | 4 | 1 |
最后一步
我们已经得到从前向后累乘与从后向前累乘的各个位置上的结果,将它们放在一起:
| nums | 1 | 2 | 3 | 4 |
|---|---|---|---|---|
| dp_forward | 1 | 1 | 2 | 6 |
| dp_backward | 24 | 12 | 4 | 1 |
答案呼之欲出,将dp_forward和dp_backward一行对应相乘得到{24,12,8,6}正是需要的输出。
我敢保证这不是偶然,让我们在分析一遍下面这个式子:
vec[i] = 前i个数累乘 * 后(length - i - 1)个数累乘
前i个数累乘正好保存在dp_forward[i]中;同理,后(length - i - 1)个数累乘正好保存在dp_backward[i]中。正因为这样,所以对应相乘,才正好是需要的答案。
进阶部分
在常数空间复杂度内完成这个题目。 出于对空间复杂度分析的目的,输出数组不被视为额外空间。
也就是说,我们最多可以使用一个大小为length的数组外加几个常数这么多的存储空间。
我的想法是从前往后这部分一定要保存在输出数组中,后面从后往前这部分可以直接更新在输出数组中。具体不在赘述,看代码里的注释更好理解。
代码
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
int length = nums.size();
// 输出数组
vector<int> vec(length, 1);
/*** 两次遍历,从前往后一次,从后往前一次 ***/
// 从前往后
int mul = 1;
for (int i = 1; i < length; i++)
{
mul *= nums[i-1];
vec[i] = mul;
}
// 从后往前
mul = 1;
for (int i = length - 2; i >= 0; i--)
{
mul *= nums[i+1];
// 更新在输出数组上,觉得抽象可以动笔画一画
vec[i] *= mul;
}
return vec;
}
};
[leetcode]238. 除自身以外数组的乘积的更多相关文章
- LeetCode 238. 除自身以外数组的乘积(Product of Array Except Self)
238. 除自身以外数组的乘积 238. Product of Array Except Self 题目描述 LeetCode LeetCode238. Product of Array Except ...
- Java实现 LeetCode 238 除自身以外数组的乘积
238. 除自身以外数组的乘积 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元 ...
- LeetCode 238. 除自身以外数组的乘积( Product of Array Except Self)
题目描述 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积. 示例: 输 ...
- [LeetCode] 238. 除自身以外数组的乘积 ☆☆☆(左积*右积)
描述 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积. 示例: 输入: ...
- leetcode 238. 除自身以外数组的乘积 (python)
给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积. 示例: 输入: [1 ...
- Leetcode题目238.除自身以外数组的乘积(中等)
题目描述: 给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积. 示例: ...
- leecode 238除自身以外数组的乘积
class Solution { public: vector<int> productExceptSelf(vector<int>& nums) { //用除法必须要 ...
- 剑指offer 66. 构建乘积数组(Leetcode 238. Product of Array Except Self)
剑指offer 66. 构建乘积数组 题目: 给定一个数组A[0, 1, ..., n-1],请构建一个数组B[0, 1, ..., n-1],其中B中的元素B[i] = A[0] * A[1] * ...
- LeetCode 81——搜索旋转排序数组 II
1. 题目 2. 解答 2.1. 方法一 基于 LeetCode 33--搜索旋转排序数组 中的方法二. 当 nums[mid] = nums[right] 时,比如 [1, 1, 2, 1, 1], ...
随机推荐
- 方案dp。。
最近经常做到组合计数的题目,每当看到这种题目第一反应总是组合数学,然后要用到排列组合公式,以及容斥原理之类的..然后想啊想,最后还是不会做.. 但是比赛完之后一看,竟然是dp..例如前几天的口号匹配求 ...
- 在CentOS上安装GITLAB
为什么要用gitlab? 方便地管理项目,设置用户权限. 参考 https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md 步 ...
- XML Publisher 并发程序由于"输出提交处理程序提交失败
http://www.cnblogs.com/benio/archive/2012/03/30/2424900.html xmlp 报表运行完成后,状态为warning,其原因大概有以下3类:1.&q ...
- css中“~”和“>”是什么意思
p~ul选择器 p之后出现的所有ul. 两种元素必须拥有相同的父元素,但是 ul不必直接紧随 p. css中“>”是: css3特有的选择器,A>B 表示选择A元素的所有子B元素. 与A ...
- C# json字符串转为对象
方法1: using System.Web.Script.Serialization; string ss = "{\"NewsCount\":\"3482\& ...
- 文件压缩小项目haffman压缩
文件压缩的原理: 文件压缩总体可以分为有损压缩和无损压缩两类,有损压缩是指对mp3等格式的文件,忽略一些无关紧要的信息,只保留一些关键的信息,但并不因此影响用户对于这些mp3格式文件的体验度,无损压缩 ...
- Runtime 全方位装逼指南
Runtime是什么?见名知意,其概念无非就是“因为 Objective-C 是一门动态语言,所以它需要一个运行时系统……这就是 Runtime 系统”云云.对博主这种菜鸟而言,Runtime 在实际 ...
- 如何使用gradle打jar包
1.进入工程目录,输入./gradlew,如显示"... build success" 则表示当前目录下gradle可用:如当前目录下无gradle,则在线下载 .. 2.输入./ ...
- 剑指offer十四之链表中倒数第k个结点
一.题目 输入一个链表,输出该链表中倒数第k个结点. 二.思路 两个指针,先让第一个指针和第二个指针都指向头结点,然后再让第一个指正走(k-1)步,到达第k个节点.然后两个指针同时往后移动,当第一个结 ...
- gitlab基本的命令
1) 远程仓库相关命令 检出仓库:$ git clone git://github.com/jquery/jquery.git 查看远程仓库:$ git remote -v 添加远程仓库:$ git ...