[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], ...
随机推荐
- SRM468
250pt 给定手机0-9按键对应的英文字母(1个对多个),0固定对应空格.然后在给定一些单词.以及一个要处理的串,叫你按照那个串模拟输出结果 思路: 大模拟,写的有点乱 // BEGIN CUT H ...
- robotium测试创建java文件和junit文件区别
两者本身差别不大,只是构造方式不同,我一般都用java文件来创建. 1.当有源码测试时,创建junit测试文件 ActivityInstrumentationTestCase2<T>T可以 ...
- 调用azkaban接口,upload 本地zip文件
使用azkaban部署任务,可以将job文件打成zip包,通过web页面上传. 如图 但是当我们实践CI持续化部署的时候,要实现自动的部署上线. 这时就要调用azkaban提供的api. 地址如下:h ...
- HDU 4920 矩阵乘积 优化
Matrix multiplication Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/ ...
- wpf Listbox 实现按住ctrl键来取消选中
1. 首先继承一个listbox,来获得按住ctrl键时,点击的item public class ListBoxEx : ListBox { public BeatTemplateWave GetA ...
- WPF 分享一种背景动画效果
今天看微软的一个Samples,发现一个蛮好玩的背景样式,如下图所示: 风格比较卡哇伊. <Window x:Class="WPFSamplesTest.MainWindow" ...
- 关于css3中的flex
参考几篇文章: Flex 布局语法教程 IE10中的Flexible Box("Flexbox")布局 “老”的Flexbox和“新”的Flexbox 一个可以练习的地方: NEW ...
- DOM扩展:DOM API的进一步增强[总结篇-下]
本文承接<DOM扩展:DOM API的进一步增强[总结篇-上]>,继续总结DOM扩展相关的功能和API. 3.6 插入标记 DOM1级中的接口已经提供了向文档中插入内容的接口,但是在给文档 ...
- DS博客作业03—栈和队列
1.本周学习总结 本周学习了栈和队列两种数据结构,分别对应后进先出,先进先出两种数据操作 学会栈的特殊类型-共享栈,队列的特殊类型-循环队列的一系列操作 学会熟练使用栈和队列的STL容器,使代码简洁 ...
- JS获取浏览器URL中查询字符串的参数
首先要知道Location这个对象以及这个对象中的一些属性: href:设置或返回完整的url.如本博客首页返回http://www.cnblogs.com/wymninja/ host:设置或返回主 ...