构建乘积数组

构建乘积数组

http://www.nowcoder.com/questionTerminal/94a4d381a68b47b7a8bed86f2975db46

题目的主要信息:
  • 给定一个数组A,要求返回数组B,数组B每个元素等于数组A所有元素除了对应下标以外的全部元素的乘积
  • B[i]=A[0]A[1]...A[i1]A[i+1]...A[n1]B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]
  • 程序不能使用除法
举一反三:

学习完本题的思路你可以解决如下题目:

JZ17. 打印从1到最大的n位数

JZ64. 求1+2+3+...+n

方法:双向遍历(推荐使用)

思路:

alt

如上图所示,矩阵中由对角线1将其分成了上三角和下三角。我们先看下三角,如果我们累乘的时候,B[1]是在B[0]的基础上乘了新增的一个A[0],B[2]是在B[1]的基础上乘了新增的一个A[1],那我们可以遍历数组的过程中不断将数组B的前一个数与数组A的前一个数相乘就得到了下三角中数组B的当前数。同理啊,我们在上三角中,用一个变量存储从右到左的累乘,每次只会多乘上一个数字。这样,两次遍历就可以解决。

具体做法:

  • step 1:初始化数组B,第一个元素为1.
  • step 2:从左到右遍历数组A,将数组B的前一个数与数组A的前一个数相乘就得到了下三角中数组B的当前数。
  • step 3:再从右到左遍历数组A,用一个数字记录从右到左上三角中的累乘,每次只会乘上一个数,同时给数组B对应部分也乘上该累乘。

图示:

alt

Java实现代码:

import java.util.ArrayList;
public class Solution {
    public int[] multiply(int[] A) {
        //初始化数组B
        int[] B = new int[A.length];
        B[0] = 1;
        //先乘左边,从左到右
        for(int i = 1; i < A.length; i++)
            //每多一位由数组B左边的元素多乘一个前面A的元素
            B[i] = B[i - 1] * A[i - 1];
        int temp = 1;
        //再乘右边,从右到左
        for(int i = A.length - 1; i >= 0; i--){
            //temp为右边的累乘
            B[i] *= temp;
            temp *= A[i];
        }
        return B;
    }
}

C++实现代码:

class Solution {
public:
    vector<int> multiply(const vector<int>& A) {
        //初始化数组B
        vector<int> B(A.size(), 1);
        //先乘左边,从左到右
        for(int i = 1; i < A.size(); i++)
            //每多一位由数组B左边的元素多乘一个前面A的元素
            B[i] = B[i - 1] * A[i - 1];
        int temp = 1;
        //再乘右边,从右到左
        for(int i = A.size() - 1; i >= 0; i--){
            //temp为右边的累乘
            B[i] *= temp;
            temp *= A[i];
        }
        return B;
    }
};

Python实现代码:

class Solution:
    def multiply(self , A: List[int]) -> List[int]:
        #初始化数组B
        B = [1 for i in range(len(A))]
        #先乘左边,从左到右
        for i in range(1, len(A)):
            #每多一位由数组B左边的元素多乘一个前面A的元素
            B[i] = B[i - 1] * A[i - 1]
        temp = 1
        #再乘右边,从右到左
        for i in reversed(range(len(A))):
            #temp为右边的累乘
            B[i] *= temp
            temp *= A[i]
        return B

复杂度分析:

  • 时间复杂度:O(n)O(n),其中nn为数组A的长度,遍历两次数组
  • 空间复杂度:O(1)O(1),数组B为返回必要空间,不属于额外空间
全部评论
新建了一个数组,空间复杂度不应该是O(n)吗?
5 回复 分享
发布于 2020-10-13 10:52
应该是B[0]=1吧,否则都为0
3 回复 分享
发布于 2020-08-19 23:24
妙啊妙啊
1 回复 分享
发布于 2021-06-12 17:37
这道题去看leetcode上面的解法好一点,说得更清楚,包括tmp(用作一个临时的从A[4]开始往上累乘的一个临时变量)
1 回复 分享
发布于 2020-12-08 16:40
讲解一点不清晰,凭啥left[i-1]和right[i+1]就必须为1?
点赞 回复 分享
发布于 2022-03-27 22:23
妙啊妙啊
点赞 回复 分享
发布于 2021-06-12 17:40
想问一下为啥使用除法非常简答?使用除法的话数组中有0不就完蛋了吗?还是我的思路有问题,我想的除法是,先把A所有元素乘起来,再除以A[i]
点赞 回复 分享
发布于 2021-02-07 23:47
这个临时变量tmp什么含义
点赞 回复 分享
发布于 2020-08-28 14:59
A[0]=1,这个也要给吧。要不后边都是0。
点赞 回复 分享
发布于 2020-07-10 21:13

相关推荐

04-08 21:39
已编辑
Java
点赞 评论 收藏
分享
04-16 10:27
已编辑
美团_Saas_后端开发
今天周一休息,突发奇想写一篇阶段总结。如题,我已经去了一个和Java彻底毫无关联的行业。曾经我以为自己能在计算机行业发光发热,拿到美团offer那会感觉自己天都亮了。没想到刚入行一年多就当了逃兵。从最开始的热爱到现在一看到代码就厌恶,不知道自己经历了什么。所以我去干什么了?答案是:在成都当了租房销售。上班那会压力大了就念叨着去干租房中介,但是一直下不去这个决心,想着自己学了四年多的计算机知识,终究还是不甘心。终于在某一天准备八股文的时候,看着无数篇和工作内容关系不大的理论知识,那一刻下定决心,决定尝试一下销售行业,也算是给自己一个交代。后面阴差阳错的投了成都自如去当租房管家,没想到面试很顺利,在当天一百多个面试的人里面,我成为了为数不多通过的几个幸运儿之一。目前已经培训通过,正式入职,也开了单,有压力但是每天过得很开心,真心喜欢那种和人交流的感觉,哪怕是最后没有选择找我租房。说这些也是想告诉那些大三,大四正在找Java实习而焦虑的同学:你们现在还年轻,选择很多,容错率也很高,可以尽情去尝试自己喜欢的行业和工作。不用因为某一次的面试没通过或者简历石沉大海而焦虑,更不用因为身边人都在挤编程的独木桥就强迫自己跟风。也算是自己的碎碎念吧,也希望自己能在新的领域取得一点小成就。也祝牛油工作顺利!
沉淀小子:干啥都不丢人啊,生存是必须要的,销售很考验一个人综合素质能力的,好的销售人脉和资源可不比写字楼的白领差啊
点赞 评论 收藏
分享
评论
89
8
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务