一道不简单又简单的Google面试题
2014-12-01 15:04
344 查看
早上醒来,拿着ipad随便找了点题提提神,正好发现了一道google面试的算法题。题目如下:
“给你一个数组A[0..n],请你在O(n)的时间里构造一个新的数组B[0..n],使得B[i]=A[0]*A[1]*A[2]*…*A
/A[i],但是不能使用除法运算。”
这道题看似不好做,实际上换个角度考虑是很简单的。有的人一分钟就想出来了,有的人要一个小时,而且想了很久去看答案的你肯定会抓狂:P
题目的重点(不能说是难点)在于不能使用除法,而恰巧这一点是计算机的思维,为什么会这么说?因为如果叫你用笔算,你会先全部乘起来再除以A[i]么?肯定不会,你绝对会把A[i]消掉。
举个例子来说。比如A有10个数,我们现在要算B[5],在纸上演算的过程就一定是 A[0]*A[1]*A[2]*A[3]*A[4] * A[6]*A[7]*A[8]*A[9]
这个时候可以发现,整个计算过程就是先算A[0~4]的乘积,再算A[6~9]的乘积,然后两者再乘起来。So,答案浮出水面,只要针对每一个下标,算出前后两部分的乘积,则该下标对应的值就是这两部分乘积的乘积。不过这种做法是典型的“空间换时间”
测试代码如下,可以参考下:
随机的执行结果:
后来我总结了下,解题的时候一定要多动手,我以前总是只动脑子,实际上多写写你就会发现解题关键点。这道题正是我趟床上没想出来,下床后写了几步,五分钟就找到解法了。所以多写写总会有好处的。
“给你一个数组A[0..n],请你在O(n)的时间里构造一个新的数组B[0..n],使得B[i]=A[0]*A[1]*A[2]*…*A
/A[i],但是不能使用除法运算。”
这道题看似不好做,实际上换个角度考虑是很简单的。有的人一分钟就想出来了,有的人要一个小时,而且想了很久去看答案的你肯定会抓狂:P
题目的重点(不能说是难点)在于不能使用除法,而恰巧这一点是计算机的思维,为什么会这么说?因为如果叫你用笔算,你会先全部乘起来再除以A[i]么?肯定不会,你绝对会把A[i]消掉。
举个例子来说。比如A有10个数,我们现在要算B[5],在纸上演算的过程就一定是 A[0]*A[1]*A[2]*A[3]*A[4] * A[6]*A[7]*A[8]*A[9]
这个时候可以发现,整个计算过程就是先算A[0~4]的乘积,再算A[6~9]的乘积,然后两者再乘起来。So,答案浮出水面,只要针对每一个下标,算出前后两部分的乘积,则该下标对应的值就是这两部分乘积的乘积。不过这种做法是典型的“空间换时间”
测试代码如下,可以参考下:
import java.util.Random; /** * * 给你一个数组A[0..n],请你在O(n)的时间里构造一个新的数组B[0..n],使得B[i]=A[0]*A[1]*A[2]*…*A /A[i],但是不能使用除法运算。 * * Created by Luonanqin on 12/1/14. */ public class ArrayA2ArrayB { public static int[] buildArrayB(int[] arrayA) { int len = arrayA.length; int[] order = new int[len]; int[] invertedOrder = new int[len]; order[0] = 1; invertedOrder[len - 1] = 1; // 计算两部分乘积只需要一个循环就可以搞定,虽然说两个单独循环不影响大O,但是当然时间越节省越好 for (int i = 1; i < len; i++) { // 计算从前到后依次的乘积,即 // order[1] = order[0] * A[1] // order[2] = order[0] * A[1] * A[2] = order[1] * A[2] // 直到order =order[n-2]*A[n-1] order[i] = arrayA[i - 1] * order[i - 1]; // 计算从后到前的乘积,即 // invertedOrder[n-1] = invertedOrder * A // invertedOrder[n-2] = invertedOrder * A * A[n-1] = invertedOrder[n-1] * A[n-1] // 直到invertedOrder[0] = invertedOrder[1] * A[1] invertedOrder[len - i - 1] = arrayA[len - i] * invertedOrder[len - i]; } int[] arrayB = new int[arrayA.length]; for (int i = 0; i < arrayB.length; i++) { arrayB[i] = order[i] * invertedOrder[i]; } return arrayB; } public static void main(String[] args) { int[] arrayA = new int[10]; Random r = new Random(System.currentTimeMillis()); for (int i = 0; i < arrayA.length; i++) { int num = 0; // 随机产生小于10的数值,但不能为0 while ((num = r.nextInt(10)) == 0) ; arrayA[i] = num; } // 打印数组A System.out.print("Array A: "); for (int i = 0; i < arrayA.length; i++) { System.out.print(arrayA[i]); if (i < arrayA.length - 1) { System.out.print(", "); } } System.out.println(); // 打印数组B int[] arrayB = buildArrayB(arrayA); System.out.print("Array B: "); for (int i = 0; i < arrayB.length; i++) { System.out.print(arrayB[i]); if (i < arrayB.length - 1) { System.out.print(", "); } } } }
随机的执行结果:
Array A: 5, 4, 2, 1, 8, 7, 1, 3, 1, 1 Array B: 1344, 1680, 3360, 6720, 840, 960, 6720, 2240, 6720, 6720
后来我总结了下,解题的时候一定要多动手,我以前总是只动脑子,实际上多写写你就会发现解题关键点。这道题正是我趟床上没想出来,下床后写了几步,五分钟就找到解法了。所以多写写总会有好处的。
相关文章推荐
- 一道比较简单的Google面试题
- Google 的一道面试题的解法
- 解答Google的一道面试题
- 一道简单的面试题
- 一道简单的面试题(求较小的值,不能用 比较运算符 if-else ?: while for 内嵌汇编 递归 第三方函数)(zt)
- 转载:解答Google的一道面试题
- google的一道JAVA面试题!!!
- 一道简单的google笔试题
- 关于一道google面试题的java算法
- 【题目22】传说中的微软面试题一道(简单题)
- 解答Google的一道面试题
- 简单一道排序题,考倒多少读书人!——从华为一道面试题浅谈计算机专业在校大学生该如何学习专业课程,信心百倍挑战就业!
- google的一道面试题
- google的一道JAVA面试题
- 一道google电话面试题
- 解答Google的一道面试题 收藏
- 两个鸡蛋--一道Google面试题
- google的一道JAVA面试题!!!
- 一道Google面试题
- 今天面试笔试了一道SQL面试题,狠简单