[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], ...
随机推荐
- 关于Servlet中GET和POST方法的总结
JSP.Servlet中get请求和post请求的区别总结 在学习JavaWeb最初的开始阶段,大家都会遇到HttpServlet中的doGet和doPost方法.关于Servlet中get请求和 ...
- Excel表格公式大全[转]
Excel技巧网_官方微博 作者: Excel技巧网_官方微博 2016-09-23 14:05:20 举报 阅读数:21219 1.查找重复内容公式:=IF(COUNTIF(A:A,A2)> ...
- 集成算法(chapter 7 - Hands on machine learning with scikit learn and tensorflow)
Voting classifier 多种分类器分别训练,然后分别对输入(新数据)预测/分类,各个分类器的结果视为投票,投出最终结果: 训练: 投票: 为什么三个臭皮匠顶一个诸葛亮.通过大数定律直观地解 ...
- BAE上部署Ghost 0.5.1注意事项
BAE上部署Ghost可参考基本安装上述安装使用的是ghost0.4.7版本 在ghost 0.5 中为了解决测试时事件侦听器过多引发的警告,在注册single事件时,将代码由原先的 process. ...
- Flask restful API如何解决跨站请求问题
如果像下面这样只是在return的response添加header是不行的: response = make_response(jsonify(response=get_articles(ARTICL ...
- MeasureOverride和ArrangeOverride 练手项目
public class Diagnol:Panel { /// <summary> /// 测量 /// </summary> /// <param name=&quo ...
- Dubbo启动时服务检查
所谓启动时服务检查是指Dubbo在启动的时候会检查当前引用的服务是否可用,不可用会抛出异常,阻止程序的初始化,以便能在上线前快速的找到问题,默认的情况下check=true 通过设置check=fal ...
- for,while陈述
今天我们来说一下for 和while循环 Python循环语句的控制结构图如下所示: for 是Python程序员使用最多的语句,for 循环用于迭代容器对象中的元素,这些对象可以是列表.元组.字典. ...
- Java入门-类HelloWorld是公共的,应在名为HelloWorld.java的文件中声明
开始学习java了,搭好环境,notepad++中新建一个java文件,新建一个HelloWorld类, public class HelloWorld { public static void ma ...
- 解决修改css或js文件,浏览器缓存更新问题。
在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css.js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从 ...