Given an array of numbers, return array of products of all other numbers (no division)
我在一次面试中被问到这个问题,我想知道其他人会如何解决。我最喜欢Java,但是其他语言的解决方案是受欢迎的。
Given an array of numbers,
nums , return an array of numbersproducts , whereproducts[i] is the product of allnums[j], j != i .
1
2
3 Input : [1, 2, 3, 4, 5]
Output: [(2*3*4*5), (1*3*4*5), (1*2*4*5), (1*2*3*5), (1*2*3*4)]
= [120, 60, 40, 30, 24]You must do this in
O(N) without using division.
聚原润滑油方法的解释如下:诀窍是构造数组(在4个元素的情况下)
1 2 | { 1, a[0], a[0]*a[1], a[0]*a[1]*a[2], } { a[1]*a[2]*a[3], a[2]*a[3], a[3], 1, } |
这两种方法都可以分别从左边缘和右边缘开始在O(N)中进行。
然后将两个数组元素相乘得到所需的结果
我的代码如下所示:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | int a[N] // This is the input int products_below[N]; p=1; for(int i=0;i<N;++i) { products_below[i]=p; p*=a[i]; } int products_above[N]; p=1; for(int i=N-1;i>=0;--i) { products_above[i]=p; p*=a[i]; } int products[N]; // This is the result for(int i=0;i<N;++i) { products[i]=products_below[i]*products_above[i]; } |
如果你也需要在太空中是O(1),你可以这样做(这是不太清楚的imho)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | int a[N] // This is the input int products[N]; // Get the products below the current index p=1; for(int i=0;i<N;++i) { products[i]=p; p*=a[i]; } // Get the products above the curent index p=1; for(int i=N-1;i>=0;--i) { products[i]*=p; p*=a[i]; } |
这里是一个小的递归函数(在C++中)来进行建模。但它需要额外的空间(在堆栈上)。假设数组在a中,n保持数组长度,我们有
1 2 3 4 5 6 7 8 9 10 | int multiply(int *a, int fwdProduct, int indx) { int revProduct = 1; if (indx < N) { revProduct = multiply(a, fwdProduct*a[indx], indx+1); int cur = a[indx]; a[indx] = fwdProduct * revProduct; revProduct *= cur; } return revProduct; } |
这是我尝试用Java解决它的方法。为非标准格式道歉,但代码有很多重复,这是我能做的最好的使它可读的方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import java.util.Arrays; public class Products { static int[] products(int... nums) { final int N = nums.length; int[] prods = new int[N]; Arrays.fill(prods, 1); for (int i = 0, pi = 1 , j = N-1, pj = 1 ; (i < N) && (j >= 0) ; pi *= nums[i++] , pj *= nums[j--] ) { prods[i] *= pi ; prods[j] *= pj ; } return prods; } public static void main(String[] args) { System.out.println( Arrays.toString(products(1, 2, 3, 4, 5)) ); // prints"[120, 60, 40, 30, 24]" } } |
循环不变量是
杰斯迈特给了一个(漂亮的!)递归解决方案;我把它变成了这个(可怕的!)爪哇一班轮。它使用堆栈中的
1 2 3 4 5 6 7 8 9 10 | static int multiply(int[] nums, int p, int n) { return (n == nums.length) ? 1 : nums[n] * (p = multiply(nums, nums[n] * (nums[n] = p), n + 1)) + 0*(nums[n] *= p); } int[] arr = {1,2,3,4,5}; multiply(arr, 1, 0); System.out.println(Arrays.toString(arr)); // prints"[120, 60, 40, 30, 24]" |
将迈克尔安德森的解决方案翻译成哈斯克尔:
1 2 3 4 5 | otherProducts xs = zipWith (*) below above where below = scanl (*) 1 $ init xs above = tail $ scanr (*) 1 xs |
偷偷摸摸地避开"不分裂"规则:
1 2 3 4 5 6 | sum = 0.0 for i in range(a): sum += log(a[i]) for i in range(a): output[i] = exp(sum - log(a[i])) |
这里,简单而干净的解决方案具有O(N)复杂性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int[] a = {1,2,3,4,5}; int[] r = new int[a.length]; int x = 1; r[0] = 1; for (int i=1;i<a.length;i++){ r[i]=r[i-1]*a[i-1]; } for (int i=a.length-1;i>0;i--){ x=x*a[i]; r[i-1]=x*r[i-1]; } for (int i=0;i<r.length;i++){ System.out.println(r[i]); } |
C++,O(n):
1 2 3 | long long prod = accumulate(in.begin(), in.end(), 1LL, multiplies<int>()); transform(in.begin(), in.end(), back_inserter(res), bind1st(divides<long long>(), prod)); |
o(n)
这是我在现代C++中的解决方案。它利用了
在线代码(Wandbox)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | #include #include<iostream> #include<vector> using namespace std; vector<int>& multiply_up(vector<int>& v){ v.insert(v.begin(),1); transform(v.begin()+1, v.end() ,v.begin() ,v.begin()+1 ,[](auto const& a, auto const& b) { return b*a; } ); v.pop_back(); return v; } int main() { vector<int> v = {1,2,3,4,5}; auto vr = v; reverse(vr.begin(),vr.end()); multiply_up(v); multiply_up(vr); reverse(vr.begin(),vr.end()); transform(v.begin(),v.end() ,vr.begin() ,v.begin() ,[](auto const& a, auto const& b) { return b*a; } ); for(auto& i: v) cout << i <<""; } |
这是O(n^2),但F很漂亮:
1 2 3 | List.fold (fun seed i -> List.mapi (fun j x -> if i=j+1 then x else x*i) seed) [1;1;1;1;1] [1..5] |
还有一个O(n^(3/2))非最优解。不过,这很有趣。
首先预处理大小为n^0.5的每个部分乘法(这是在o(n)时间复杂度下完成的)。然后,可以在2*o(n^0.5)时间内计算每个数字的其他值的倍数(为什么?因为您只需要将其他((n^0.5)-1)数字的最后一个元素乘以(n^0.5)-1)个属于当前数字组的数字。对每个数字执行此操作,可以获得O(n^(3/2))时间。
例子:
4 6 7 2 3 1 9 5 8
部分结果:4×6×7=1682×3×1=69×5×8=360
要计算3的值,需要将其他组的值168*360相乘,然后再乘以2*1。
这里要完成的是scala中的代码:
1 2 | val list1 = List(1, 2, 3, 4, 5) for (elem <- list1) println(list1.filter(_ != elem) reduceLeft(_*_)) |
这将打印出以下内容:
1 2 3 4 5 | 120 60 40 30 24 |
程序将过滤掉当前的电子元件。=elem);并将新列表与reducecleft方法相乘。我认为如果您使用scala视图或迭代器进行懒惰的eval,这将是O(N)。
1 2 3 4 5 6 7 | def productify(arr, prod, i): if i < len(arr): prod.append(arr[i - 1] * prod[i - 1]) if i > 0 else prod.append(1) retval = productify(arr, prod, i + 1) prod[i] *= retval return retval * arr[i] return 1 |
arr=[1,2,3,4,5]PROD=生产(arr,prod,0)打印戳
预先计算每个元素左边和右边的数字的乘积。对于每一个元素,期望的价值都是它的邻居产品的产物。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | #include <stdio.h> unsigned array[5] = { 1,2,3,4,5}; int main(void) { unsigned idx; unsigned left[5] , right[5]; left[0] = 1; right[4] = 1; /* calculate products of numbers to the left of [idx] */ for (idx=1; idx < 5; idx++) { left[idx] = left[idx-1] * array[idx-1]; } /* calculate products of numbers to the right of [idx] */ for (idx=4; idx-- > 0; ) { right[idx] = right[idx+1] * array[idx+1]; } for (idx=0; idx <5 ; idx++) { printf("[%u] Product(%u*%u) = %u " , idx, left[idx] , right[idx] , left[idx] * right[idx] ); } return 0; } |
结果:
1 2 3 4 5 6 | $ ./a.out [0] Product(1*120) = 120 [1] Product(1*60) = 60 [2] Product(2*20) = 40 [3] Product(6*5) = 30 [4] Product(24*1) = 24 |
(更新:现在我再仔细看一看,这个方法与上面的迈克尔·安德森、丹尼尔·米戈夫斯基和多基因润滑剂的方法相同)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | public static void main(String[] args) { int[] arr = { 1, 2, 3, 4, 5 }; int[] result = { 1, 1, 1, 1, 1 }; for (int i = 0; i < arr.length; i++) { for (int j = 0; j < i; j++) { result[i] *= arr[j]; } for (int k = arr.length - 1; k > i; k--) { result[i] *= arr[k]; } } for (int i : result) { System.out.println(i); } } |
我想出了这个解决方案,我发现它是如此清晰,你认为呢!?
基于billz答案——抱歉,我不能发表评论,但这里有一个scala版本,它可以正确处理列表中的重复项,可能是o(n):
1 2 3 | val list1 = List(1, 7, 3, 3, 4, 4) val view = list1.view.zipWithIndex map { x => list1.view.patch(x._2, Nil, 1).reduceLeft(_*_)} view.force |
返回:
1 | List(1008, 144, 336, 336, 252, 252) |
在这里添加我的javascript解决方案,因为我找不到任何人建议这样做。除了计算从另一个数字中提取一个数字的次数之外,要除法是什么?我计算了整个数组的积,然后迭代每个元素,并将当前元素减至零:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | //No division operation allowed // keep substracting divisor from dividend, until dividend is zero or less than divisor function calculateProducsExceptCurrent_NoDivision(input){ var res = []; var totalProduct = 1; //calculate the total product for(var i = 0; i < input.length; i++){ totalProduct = totalProduct * input[i]; } //populate the result array by"dividing" each value for(var i = 0; i < input.length; i++){ var timesSubstracted = 0; var divisor = input[i]; var dividend = totalProduct; while(divisor <= dividend){ dividend = dividend - divisor; timesSubstracted++; } res.push(timesSubstracted); } return res; } |
我习惯于C:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | public int[] ProductExceptSelf(int[] nums) { int[] returnArray = new int[nums.Length]; List<int> auxList = new List<int>(); int multTotal = 0; // If no zeros are contained in the array you only have to calculate it once if(!nums.Contains(0)) { multTotal = nums.ToList().Aggregate((a, b) => a * b); for (int i = 0; i < nums.Length; i++) { returnArray[i] = multTotal / nums[i]; } } else { for (int i = 0; i < nums.Length; i++) { auxList = nums.ToList(); auxList.RemoveAt(i); if (!auxList.Contains(0)) { returnArray[i] = auxList.Aggregate((a, b) => a * b); } else { returnArray[i] = 0; } } } return returnArray; } |
阿德里安·索斯:
使用以下内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public int[] calc(int[] params) { int[] left = new int[n-1] in[] right = new int[n-1] int fac1 = 1; int fac2 = 1; for( int i=0; i<n; i++ ) { fac1 = fac1 * params[i]; fac2 = fac2 * params[n-i]; left[i] = fac1; right[i] = fac2; } fac = 1; int[] results = new int[n]; for( int i=0; i<n; i++ ) { results[i] = left[i] * right[i]; } |
是的,我肯定我错过了一些I-1而不是I,但这是解决问题的方法。
这是我的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | int multiply(int a[],int n,int nextproduct,int i) { int prevproduct=1; if(i>=n) return prevproduct; prevproduct=multiply(a,n,nextproduct*a[i],i+1); printf(" i=%d > %d ",i,prevproduct*nextproduct); return prevproduct*a[i]; } int main() { int a[]={2,4,1,3,5}; multiply(a,5,1,0); return 0; } |
下面是一个稍微实用的例子,使用c:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | Func<long>[] backwards = new Func<long>[input.Length]; Func<long>[] forwards = new Func<long>[input.Length]; for (int i = 0; i < input.Length; ++i) { var localIndex = i; backwards[i] = () => (localIndex > 0 ? backwards[localIndex - 1]() : 1) * input[localIndex]; forwards[i] = () => (localIndex < input.Length - 1 ? forwards[localIndex + 1]() : 1) * input[localIndex]; } var output = new long[input.Length]; for (int i = 0; i < input.Length; ++i) { if (0 == i) { output[i] = forwards[i + 1](); } else if (input.Length - 1 == i) { output[i] = backwards[i - 1](); } else { output[i] = forwards[i + 1]() * backwards[i - 1](); } } |
由于所创建函数的半递归性,我并不完全确定这是O(N),但我的测试似乎表明它是O(N)的时间。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | {- Recursive solution using sqrt(n) subsets. Runs in O(n). Recursively computes the solution on sqrt(n) subsets of size sqrt(n). Then recurses on the product sum of each subset. Then for each element in each subset, it computes the product with the product sum of all other products. Then flattens all subsets. Recurrence on the run time is T(n) = sqrt(n)*T(sqrt(n)) + T(sqrt(n)) + n Suppose that T(n) ≤ cn in O(n). T(n) = sqrt(n)*T(sqrt(n)) + T(sqrt(n)) + n ≤ sqrt(n)*c*sqrt(n) + c*sqrt(n) + n ≤ c*n + c*sqrt(n) + n ≤ (2c+1)*n ∈ O(n) Note that ceiling(sqrt(n)) can be computed using a binary search and O(logn) iterations, if the sqrt instruction is not permitted. -} otherProducts [] = [] otherProducts [x] = [1] otherProducts [x,y] = [y,x] otherProducts a = foldl' (++) [] $ zipWith (\s p -> map (*p) s) solvedSubsets subsetOtherProducts where n = length a -- Subset size. Require that 1 < s < n. s = ceiling $ sqrt $ fromIntegral n solvedSubsets = map otherProducts subsets subsetOtherProducts = otherProducts $ map product subsets subsets = reverse $ loop a [] where loop [] acc = acc loop a acc = loop (drop s a) ((take s a):acc) |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | function solution($array) { $result = []; foreach($array as $key => $value){ $copyOfOriginalArray = $array; unset($copyOfOriginalArray[$key]); $result[$key] = multiplyAllElemets($copyOfOriginalArray); } return $result; } /** * multiplies all elements of array * @param $array * @return int */ function multiplyAllElemets($array){ $result = 1; foreach($array as $element){ $result *= $element; } return $result; } $array = [1, 9, 2, 7]; print_r(solution($array)); |
这个解决方案可以被认为是C/C++。假设我们有一个包含n个元素的数组"a"就像一个[N],那么伪代码如下。
1 2 3 4 5 6 7 8 9 10 11 | for(j=0;j<n;j++) { prod[j]=1; for (i=0;i<n;i++) { if(i==j) continue; else prod[j]=prod[j]*a[i]; } |
另一个解决方案,使用除法。两次遍历。将所有元素相乘,然后开始除以每个元素。
我最近被问到这个问题,虽然我不能在这个过程中得到O(N),但我有一个不同的方法(不幸的是O(N^2)),但我想我还是会分享。
先转换成
循环通过原始数组
使用
1 2 3 4 | while (temp < list.size() - 1) { res *= list.get(temp); temp++; } |
然后将
我知道这没什么用,但这是我在面试压力下想出来的。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int[] array = new int[]{1, 2, 3, 4, 5}; List<Integer> list = Arrays.stream(array).boxed().collect(Collectors.toList()); int[] newarray = new int[array.length]; int res = 1; for (int i = 0; i < array.length; i++) { int temp = i; while (temp < list.size() - 1) { res *= list.get(temp); temp++; } newarray[i] = res; list.add(array[i]); res = 1; } |
Output: [24, 120, 60, 40, 30]
红宝石溶液
1 2 3 4 | a = [1,2,3,4] result = [] a.each {|x| result.push( (a-[x]).reject(&:zero?).reduce(:*)) } puts result |
这是一个C实现o(n)时间复杂性。输入
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | #include<stdio.h> int main() { int x; printf("Enter The Size of Array :"); scanf("%d",&x); int array[x-1],i ; printf("Enter The Value of Array : "); for( i = 0 ; i <= x-1 ; i++) { printf("Array[%d] =",i); scanf("%d",&array[i]); } int left[x-1] , right[x-1]; left[0] = 1 ; right[x-1] = 1 ; for( i = 1 ; i <= x-1 ; i++) { left[i] = left[i-1] * array[i-1]; } printf(" This is Multiplication of array[i-1] and left[i-1] "); for( i = 0 ; i <= x-1 ; i++) { printf("Array[%d] = %d , Left[%d] = %d ",i,array[i],i,left[i]); } for( i = x-2 ; i >= 0 ; i--) { right[i] = right[i+1] * array[i+1]; } printf(" This is Multiplication of array[i+1] and right[i+1] "); for( i = 0 ; i <= x-1 ; i++) { printf("Array[%d] = %d , Right[%d] = %d ",i,array[i],i,right[i]); } printf(" This is Multiplication of Right[i] * Left[i] "); for( i = 0 ; i <= x-1 ; i++) { printf("Right[%d] * left[%d] = %d * %d = %d ",i,i,right[i],left[i],right[i]*left[i]); } return 0 ; } |
产量
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | Enter The Size of Array : 5 Enter The Value of Array : Array[0] = 1 Array[1] = 2 Array[2] = 3 Array[3] = 4 Array[4] = 5 This is Multiplication of array[i-1] and left[i-1] Array[0] = 1 , Left[0] = 1 Array[1] = 2 , Left[1] = 1 Array[2] = 3 , Left[2] = 2 Array[3] = 4 , Left[3] = 6 Array[4] = 5 , Left[4] = 24 This is Multiplication of array[i+1] and right[i+1] Array[0] = 1 , Right[0] = 120 Array[1] = 2 , Right[1] = 60 Array[2] = 3 , Right[2] = 20 Array[3] = 4 , Right[3] = 5 Array[4] = 5 , Right[4] = 1 This is Multiplication of Right[i] * Left[i] Right[0] * left[0] = 120 * 1 = 120 Right[1] * left[1] = 60 * 1 = 60 Right[2] * left[2] = 20 * 2 = 40 Right[3] * left[3] = 5 * 6 = 30 Right[4] * left[4] = 1 * 24 = 24 Process returned 0 (0x0) execution time : 6.548 s Press any key to continue. |
下面是我使用Python的简明解决方案。
1 2 3 4 5 6 7 8 | from functools import reduce def excludeProductList(nums_): after = [reduce(lambda x, y: x*y, nums_[i:]) for i in range(1, len(nums_))] + [1] before = [1] + [reduce(lambda x, y: x*y, nums_[:i]) for i in range(1, len(nums_))] zippedList = list(zip(before, after)) finalList = list(map(lambda x: x[0]*x[1], zippedList)) return finalList |
我的第一次尝试,在Python。O(2n):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | def product(l): product = 1 num_zeroes = 0 pos_zero = -1 # Multiply all and set positions for i, x in enumerate(l): if x != 0: product *= x l[i] = 1.0/x else: num_zeroes += 1 pos_zero = i # Warning! Zeroes ahead! if num_zeroes > 0: l = [0] * len(l) if num_zeroes == 1: l[pos_zero] = product else: # Now set the definitive elements for i in range(len(l)): l[i] = int(l[i] * product) return l if __name__ =="__main__": print("[0, 0, 4] =" + str(product([0, 0, 4]))) print("[3, 0, 4] =" + str(product([3, 0, 4]))) print("[1, 2, 3] =" + str(product([1, 2, 3]))) print("[2, 3, 4, 5, 6] =" + str(product([2, 3, 4, 5, 6]))) print("[2, 1, 2, 2, 3] =" + str(product([2, 1, 2, 2, 3]))) |
输出:
1 2 3 4 5 | [0, 0, 4] = [0, 0, 0] [3, 0, 4] = [0, 12, 0] [1, 2, 3] = [6, 3, 2] [2, 3, 4, 5, 6] = [360, 240, 180, 144, 120] [2, 1, 2, 2, 3] = [12, 24, 12, 12, 8] |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import java.util.Arrays; public class Pratik { public static void main(String[] args) { int[] array = {2, 3, 4, 5, 6}; // OUTPUT: 360 240 180 144 120 int[] products = new int[array.length]; arrayProduct(array, products); System.out.println(Arrays.toString(products)); } public static void arrayProduct(int array[], int products[]) { double sum = 0, EPSILON = 1e-9; for(int i = 0; i < array.length; i++) sum += Math.log(array[i]); for(int i = 0; i < array.length; i++) products[i] = (int) (EPSILON + Math.exp(sum - Math.log(array[i]))); } } |
输出:
1 | [360, 240, 180, 144, 120] |
Time complexity : O(n)
Space complexity: O(1)
//这是Java中的递归解决方案//从主产品(a,1,0)调用如下;
1 2 3 4 5 6 7 8 9 10 | public static double product(double[] a, double fwdprod, int index){ double revprod = 1; if (index < a.length){ revprod = product2(a, fwdprod*a[index], index+1); double cur = a[index]; a[index] = fwdprod * revprod; revprod *= cur; } return revprod; } |
以下是线性o(n)时间的简单scala版本:
1 2 3 4 5 6 7 8 9 10 11 12 | def getProductEff(in:Seq[Int]):Seq[Int] = { //create a list which has product of every element to the left of this element val fromLeft = in.foldLeft((1, Seq.empty[Int]))((ac, i) => (i * ac._1, ac._2 :+ ac._1))._2 //create a list which has product of every element to the right of this element, which is the same as the previous step but in reverse val fromRight = in.reverse.foldLeft((1,Seq.empty[Int]))((ac,i) => (i * ac._1,ac._2 :+ ac._1))._2.reverse //merge the two list by product at index in.indices.map(i => fromLeft(i) * fromRight(i)) } |
这是因为基本上答案是一个数组,它的所有元素的乘积都在左边和右边。
具有O(N)运行时的整洁解决方案:
为元素i创建最终数组"result",
1 | result[i] = pre[i-1]*post[i+1]; |
这是PTYHON版本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | # This solution use O(n) time and O(n) space def productExceptSelf(self, nums): """ :type nums: List[int] :rtype: List[int] """ N = len(nums) if N == 0: return # Initialzie list of 1, size N l_prods, r_prods = [1]*N, [1]*N for i in range(1, N): l_prods[i] = l_prods[i-1] * nums[i-1] for i in reversed(range(N-1)): r_prods[i] = r_prods[i+1] * nums[i+1] result = [x*y for x,y in zip(l_prods,r_prods)] return result # This solution use O(n) time and O(1) space def productExceptSelfSpaceOptimized(self, nums): """ :type nums: List[int] :rtype: List[int] """ N = len(nums) if N == 0: return # Initialzie list of 1, size N result = [1]*N for i in range(1, N): result[i] = result[i-1] * nums[i-1] r_prod = 1 for i in reversed(range(N)): result[i] *= r_prod r_prod *= nums[i] return result |
我有一个关于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public static int[] findEachElementAsProduct1(final int[] arr) { int len = arr.length; // int[] product = new int[len]; // Arrays.fill(product, 1); int[] product = IntStream.generate(() -> 1).limit(len).toArray(); for (int i = 0; i < len; i++) { for (int j = 0; j < len; j++) { if (i == j) { continue; } product[i] *= arr[j]; } } return product; } |
我们可以先将
1 2 3 4 5 6 | def products(nums): return [ reduce(lambda x,y: x * y, nums[:i] + nums[i+1:]) for i in range(len(nums)) ] print products([1, 2, 3, 4, 5]) [out] [120, 60, 40, 30, 24] |
这里还有一个简单的概念,它解决了
1 2 3 4 5 6 7 | int[] arr = new int[] {1, 2, 3, 4, 5}; int[] outArray = new int[arr.length]; for(int i=0;i<arr.length;i++){ int res=Arrays.stream(arr).reduce(1, (a, b) -> a * b); outArray[i] = res/arr[i]; } System.out.println(Arrays.toString(outArray)); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | int[] b = new int[] { 1, 2, 3, 4, 5 }; int j; for(int i=0;i<b.Length;i++) { int prod = 1; int s = b[i]; for(j=i;j<b.Length-1;j++) { prod = prod * b[j + 1]; } int pos = i; while(pos!=-1) { pos--; if(pos!=-1) prod = prod * b[pos]; } Console.WriteLine(" Output is {0}",prod); } |
这是Ruby中的一个单行解决方案。
使用ECMAScript 2015编码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 | 'use strict' /* Write a function that, given an array of n integers, returns an array of all possible products using exactly (n - 1) of those integers. */ /* Correct behavior: - the output array will have the same length as the input array, ie. one result array for each skipped element - to compare result arrays properly, the arrays need to be sorted - if array lemgth is zero, result is empty array - if array length is 1, result is a single-element array of 1 input array: [1, 2, 3] 1*2 = 2 1*3 = 3 2*3 = 6 result: [2, 3, 6] */ class Test { setInput(i) { this.input = i return this } setExpected(e) { this.expected = e.sort() return this } } class FunctionTester { constructor() { this.tests = [ new Test().setInput([1, 2, 3]).setExpected([6, 3, 2]), new Test().setInput([2, 3, 4, 5, 6]).setExpected([3 * 4 * 5 * 6, 2 * 4 * 5 * 6, 2 * 3 * 5 * 6, 2 * 3 * 4 * 6, 2 * 3 * 4 * 5]), ] } test(f) { console.log('function:', f.name) this.tests.forEach((test, index) => { var heading = 'Test #' + index + ':' var actual = f(test.input) var failure = this._check(actual, test) if (!failure) console.log(heading, 'input:', test.input, 'output:', actual) else console.error(heading, failure) return !failure }) } testChain(f) { this.test(f) return this } _check(actual, test) { if (!Array.isArray(actual)) return 'BAD: actual not array' if (actual.length !== test.expected.length) return 'BAD: actual length is ' + actual.length + ' expected: ' + test.expected.length if (!actual.every(this._isNumber)) return 'BAD: some actual values are not of type number' if (!actual.sort().every(isSame)) return 'BAD: arrays not the same: [' + actual.join(', ') + '] and [' + test.expected.join(', ') + ']' function isSame(value, index) { return value === test.expected[index] } } _isNumber(v) { return typeof v === 'number' } } /* Efficient: use two iterations of an aggregate product We need two iterations, because one aggregate goes from last-to-first The first iteration populates the array with products of indices higher than the skipped index The second iteration calculates products of indices lower than the skipped index and multiplies the two aggregates input array: 1 2 3 2*3 1* 3 1*2 input array: 2 3 4 5 6 (3 * 4 * 5 * 6) (2) * 4 * 5 * 6 (2 * 3) * 5 * 6 (2 * 3 * 4) * (6) (2 * 3 * 4 * 5) big O: (n - 2) + (n - 2)+ (n - 2) = 3n - 6 => o(3n) */ function multiplier2(ns) { var result = [] if (ns.length > 1) { var lastIndex = ns.length - 1 var aggregate // for the first iteration, there is nothing to do for the last element var index = lastIndex for (var i = 0; i < lastIndex; i++) { if (!i) aggregate = ns[index] else aggregate *= ns[index] result[--index] = aggregate } // for second iteration, there is nothing to do for element 0 // aggregate does not require multiplication for element 1 // no multiplication is required for the last element for (var i = 1; i <= lastIndex; i++) { if (i === 1) aggregate = ns[0] else aggregate *= ns[i - 1] if (i !== lastIndex) result[i] *= aggregate else result[i] = aggregate } } else if (ns.length === 1) result[0] = 1 return result } /* Create the list of products by iterating over the input array the for loop is iterated once for each input element: that is n for every n, we make (n - 1) multiplications, that becomes n (n-1) O(n^2) */ function multiplier(ns) { var result = [] for (var i = 0; i < ns.length; i++) { result.push(ns.reduce((reduce, value, index) => !i && index === 1 ? value // edge case: we should skip element 0 and it's the first invocation: ignore reduce : index !== i ? reduce * value // multiply if it is not the element that should be skipped : reduce)) } return result } /* Multiply by clone the array and remove one of the integers O(n^2) and expensive array manipulation */ function multiplier0(ns) { var result = [] for (var i = 0; i < ns.length; i++) { var ns1 = ns.slice() // clone ns array ns1.splice(i, 1) // remove element i result.push(ns1.reduce((reduce, value) => reduce * value)) } return result } new FunctionTester().testChain(multiplier0).testChain(multiplier).testChain(multiplier2) |
使用node.js v4.4.5运行,如:
node --harmony integerarrays.js
1 2 3 4 5 6 7 8 9 | function: multiplier0 Test #0: input: [ 1, 2, 3 ] output: [ 2, 3, 6 ] Test #1: input: [ 2, 3, 4, 5, 6 ] output: [ 120, 144, 180, 240, 360 ] function: multiplier Test #0: input: [ 1, 2, 3 ] output: [ 2, 3, 6 ] Test #1: input: [ 2, 3, 4, 5, 6 ] output: [ 120, 144, 180, 240, 360 ] function: multiplier2 Test #0: input: [ 1, 2, 3 ] output: [ 2, 3, 6 ] Test #1: input: [ 2, 3, 4, 5, 6 ] output: [ 120, 144, 180, 240, 360 ] |
试试这个!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | import java.util.*; class arrProduct { public static void main(String args[]) { //getting the size of the array Scanner s = new Scanner(System.in); int noe = s.nextInt(); int out[]=new int[noe]; int arr[] = new int[noe]; // getting the input array for(int k=0;k<noe;k++) { arr[k]=s.nextInt(); } int val1 = 1,val2=1; for(int i=0;i<noe;i++) { int res=1; for(int j=1;j<noe;j++) { if((i+j)>(noe-1)) { int diff = (i+j)-(noe); if(arr[diff]!=0) { res = res * arr[diff]; } } else { if(arr[i+j]!=0) { res= res*arr[i+j]; } } out[i]=res; } } //printing result System.out.print("Array of Product: ["); for(int l=0;l<out.length;l++) { if(l!=out.length-1) { System.out.print(out[l]+","); } else { System.out.print(out[l]); } } System.out.print("]"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 | int[] arr1 = { 1, 2, 3, 4, 5 }; int[] product = new int[arr1.Length]; for (int i = 0; i < arr1.Length; i++) { for (int j = 0; j < product.Length; j++) { if (i != j) { product[j] = product[j] == 0 ? arr1[i] : product[j] * arr1[i]; } } } |