题目:给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。不能使用除法。

解析:这道题,直观的解法是:设置一个循环(由0到n-1),计算B[i]时,忽略掉A[i]项,把数组A中的其他项全部相乘,即得到B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]。这样,一次循环过后,就可以在没有除法的条件下,得到数组B中所有的值。那么,这种解法的时间复杂度和空间复杂度是多少呢?时间复杂度:由于循环由0~n-1,即o(n),在每次循环中,要执行n-1次乘法运算,所以这种解法的时间复杂度为o(n)*o(n-1)=o(n2);空间复杂度为o(1)。

  显然,上面这种解法的时间复杂度较高,那么有没有o(n)的解法呢?我们不妨分析一下上面这种解法的问题,从而找到可以优化的突破口。上面的复杂度由两部分组成,第一部分:循环由0~n-1,显然我们需要计算每一个B[i],不管怎样,我们都没办法去掉这样的基本循环,也就是说这一部分带来了时间复杂度o(n)不能再进行优化;第二部分:每一次计算B[i]都需要进行n-1次乘法,也即是需要计算n次n-1个数相乘,细心的人可以发现,这里面有很多的乘法是重复的,正是由于这部分重复的乘法计算造成我们的时间复杂度很高。那么,有没有办法只计算一次这样的n-1个数相乘呢?我们可以定义两个中间数组来存储已经计算过得乘法结果,这样,在进行下一个B[i]计算时,我们只需要完成一次乘法就可以得到B[i]的结果了。这样,时间复杂度就变成了o(1),整个算法时间复杂度就降成了o(n)。具体分析思路如下:

首先,我们可以将数组B表示成矩阵的形式如下:

 B[0]  1 A[1] A[2] ... A[n-2] A[n-1]
B[1] A[0] 1 A[2] ... A[n-2] A[n-1]
B[2] A[0] A[1] 1 ... A[n-2] A[n-1]
... ... ... ... 1 ... ...
B[n-2] A[0] A[1] A[2] ... 1 A[n-1]
B[n-1] A[0] A[1] A[2] ... A[n-2] 1

如上图所示,矩阵的每一行代表数组B的一个元素,从上往下,依次是B[0],B[1],...B[n-2],B[n-1]。那么,我们可以将每一个B[i]看成两部分,分别用C[i]和D[i]表示。其中C[i] = A[0]*A[1]*...*A[i-1],D[i] = A[i+1]*...*A[n-2]*A[n-1],这样,B[i]=C[i]*1*D[i]。也就是说,我们可以每次更新数组C[i]和D[i],即C[i]=C[i-1]*A[i-1]和D[i]=D[i+1]*A[i+1](需要说明的是,这里C[i]的更新是按照从前往后,而D[i]则是从后往前),从而为我们节省了大量的重复的乘法计算,使得时间复杂度降为o(n)。

int[] multiply(int[] A){
if(A==null||A.length<=0)//边界条件,最好附带上
return null;
int n = A.length;
int[] B = new int[n];
B[0]=1;
/*更新C[i],这里我们不另外定义数组,直接将C[i]的计算结果存储在B[i]中,
这样,再将D[i]的结果直接乘以B[i](此时B[i]等于C[i]),就得到了最终
的B[i],显然为我们又节省了不少空间存储。
*/
for(int i=1;i<n;i++){
B[i]=B[i-1]*A[i-1];
}
int temp =1;
//更新D[i],这里要从n-2开始,因为B[n-1]已得到最终结果
for(int j=n-2;j>=0;j--){
temp*=A[j+1];
B[j]*=temp;
}
   return B;
}

  显然,上述解法的时间复杂度为:2*o(n)*2=o(n)。

构建乘积数组--java的更多相关文章

  1. 【Java】 剑指offer(66) 构建乘积数组

      本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 给定一个数组A[0, 1, …, n-1],请构建一个数组B[ ...

  2. 剑指 Offer 66. 构建乘积数组 + 思维

    剑指 Offer 66. 构建乘积数组 Offer_66 题目描述 题解分析 java代码 package com.walegarrett.offer; /** * @Author WaleGarre ...

  3. 《剑指offer》第六十六题(构建乘积数组)

    // 面试题66:构建乘积数组 // 题目:给定一个数组A[0, 1, …, n-1],请构建一个数组B[0, 1, …, n-1],其 // 中B中的元素B[i] =A[0]×A[1]×… ×A[i ...

  4. 【剑指offer】不使用除法,构建乘积数组,C++实现

    # 题目 # 思路 设C[i] = A[0] * A[1] * - * A[i-1],D[i] =  A[i+1] * - * A[n-1],则C[i]按照从上到下的顺序计算,即C[i] = C[i- ...

  5. php实现构建乘积数组(算法:替换)(语法错误:分号和$符号)

    php实现构建乘积数组(算法:替换)(语法错误:分号和$符号) 一.总结 1.算法:替换 2.语法错误:分号和$符号 二.php实现构建乘积数组 题目描述: 给定一个数组A[0,1,...,n-1], ...

  6. 剑指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] * ...

  7. 剑指offer二刷——数组专题——构建乘积数组

    构建乘积数组 题目描述 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A ...

  8. 【剑指offer】51.构建乘积数组

    51.构建乘积数组 知识点:数组: 题目描述 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0] * A[1] *... * A[i ...

  9. 力扣 - 剑指 Offer 66. 构建乘积数组

    题目 剑指 Offer 66. 构建乘积数组 思路1 按照一般的思路就是将所有的相乘,然后除以每一位数字就是答案,但是题目要求我们不能使用除法,因此我们会想到每次遍历到每个数字的时候,在遍历一遍数组, ...

随机推荐

  1. hdu1863 畅通工程---MST&连通

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1863 题目大意: 中文题,求MST权值,如果不连通,输出? 解题思路: 这道题帮我找出了之前模板中的 ...

  2. python查看安装包

    D:\Python27\Scripts>pip listbackports.ssl-match-hostname (3.4.0.2)basicauth (0.2)certifi (14.5.14 ...

  3. java web用户登录界面

    做这次实验,主要用到了mysql  java web 的 内容 实验代码: IUserDao.java package com.jaovo.msg.dao; import java.util.List ...

  4. 安装mysql提示This application requires .NET framework 4.0.

    问题描述:安装MySQL社区版时遇到This application requires .NET framework 4.0. 解决方法:在http://search.microsoft.com/zh ...

  5. c#基础之循环探索

    前言在学习基础的语法中循环控制是程序语句控制中的一种,循环在很多的操作中都有应用,例如在获得数据库中的查询的数据之后可以用循环遍历的方式拿到每一行的数据,从而拿到每一个单元格的数据,在文件的操作中也大 ...

  6. [vijos1066]弱弱的战壕

    描述 永恒和mx正在玩一个即时战略游戏,名字嘛~~~~~~恕本人记性不好,忘了-_-b. mx在他的基地附近建立了n个战壕,每个战壕都是一个独立的作战单位,射程可以达到无限(“mx不赢定了?!?”永恒 ...

  7. linux 下备份mysql数据库

    今天老板让备份数据库没办法自己折腾吧,下面把折腾的结果总结总结. 数据库备份思路: 1.编写脚本 2.执行脚本  哈哈,是不是很简单,打开冰箱,放入大象,关上.下面我是具体操作. 一.编写脚本 1.设 ...

  8. 常用模块之 os,json,shelve,xml模块

    os 即操作系统 在 os 中提供了很多关于文件,文件夹,路径处理的函数 这是我们学习的重点 os.path 是os模块下专门用于处理路径相关的 python是一门跨平台语言,由于每个平台路径规则不同 ...

  9. python标准模块

    sys模块 这是一个跟python解释器关系密切的标准库.它提供了一些和python解释器操作密切的属性和函数. sys中常用的函数和属性: sys.argv: sys.argv是专门用来向pytho ...

  10. 使用Hbase快照将数据输出到互联网区测试环境的临时Hbase集群

    通过snapshot对内网测试环境Hbase生产集群的全量数据(包括原始数据和治理后数据)复制到互联网Hbase临时集群.工具及原理: 1)         Hbase自带镜像导出工具(snapsho ...