私は就職の面接でこの質問をされましたが、他の人がどのようにそれを解決するか知りたいです。私はJavaに最も慣れていますが、他の言語のソリューションも大歓迎です。
数値の配列
nums
を指定すると、数値の配列products
を返します。ここで、products[i]
はすべてのnums[j], j != i
の積です。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]
これは、
O(N)
で除算を使用せずに行う必要があります。
polygenelubricants メソッドの説明は次のとおりです。トリックは配列を作成することです(4つの要素の場合)
{ 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)で、それぞれ左端と右端から開始することで実行できます。
次に、2つの配列要素を要素ごとに乗算すると、必要な結果が得られます
私のコードは次のようになります。
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)である必要がある場合も、これを行うことができます(あまり明確ではありません)
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++)です。ただし、O(n)余分なスペース(スタック上)が必要です。配列がaにあり、Nが配列の長さを保持していると仮定すると、
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で解決しようとしています。非標準のフォーマットについてはおologiesびしますが、コードには多くの重複があります。これを読みやすくするためにできる最善の方法です。
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]"
}
}
ループ不変条件はpi = nums[0] * nums[1] *.. nums[i-1]
およびpj = nums[N-1] * nums[N-2] *.. nums[j+1]
です。左側のi
部分は「プレフィックス」ロジックであり、右側のj
部分は「サフィックス」ロジックです。
Jasmeet は(美しい!)再帰的な解決策を提供しました。私はこれを(恐ろしい!)Javaワンライナーに変えました。 インプレース変更を行い、スタック内のO(N)
一時スペースを使用します。
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]"
Michael AndersonのソリューションをHaskellに翻訳する:
otherProducts xs = zipWith (*) below above
where below = scanl (*) 1 $ init xs
above = tail $ scanr (*) 1 xs
「分割なし」ルールをこっそり回避:
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)を使用したシンプルでクリーンなソリューションです。
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):
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++での私のソリューションです。 std::transform
を使用しており、覚えやすいです。
#include<algorithm>
#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#はすっごく美しいです:
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]
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 = [] productify(arr、prod、0)print prod
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 = 168 2 * 3 * 1 = 6 9 * 5 * 8 = 360
3の値を計算するには、他のグループの値に168 * 360を掛け、次に2 * 1を掛ける必要があります。
Billzの回答に基づいています。申し訳ありませんが、コメントすることはできませんが、リスト内の重複アイテムを正しく処理するscalaバージョンがあり、おそらくO(n)です。
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
返却値:
List(1008, 144, 336, 336, 252, 252)
ここで完了するのは、Scalaのコードです。
val list1 = List(1, 2, 3, 4, 5)
for (elem <- list1) println(list1.filter(_ != elem) reduceLeft(_*_))
これにより、以下が出力されます。
120
60
40
30
24
プログラムは、現在のelem(_!= elem)を除外します。そして、reduceLeftメソッドで新しいリストを乗算します。遅延評価にO(n)ビューまたはIteratorを使用する場合、これはscalaになると思います。
私はC#に慣れています:
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;
}
各要素の左と右の数値の積を事前計算します。すべての要素について、望ましい値はその隣人の製品の積です。
#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\n"
, idx, left[idx] , right[idx] , left[idx] * right[idx] );
}
return 0;
}
結果:
$ ./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
(更新:今私はよく見ます、これはマイケル・アンダーソン、ダニエル・ミゴウスキーと上記のポリジェネラブリカントと同じ方法を使用します)
トリッキー:
以下を使用してください。
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の代わりにi-1を逃しましたが、それはそれを解決する方法です。
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);
}
}
この解決策を思いつきましたが、どう思いますか?
これを提案する人が見つからなかったので、ここに私のjavascriptソリューションを追加します。別の数字から数字を抽出できる回数をカウントすることを除いて、分割することは何ですか?配列全体の積を計算し、各要素を反復処理して、現在の要素をゼロまで減算しました。
//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の実装です
O(n)時間の複雑さ。
入力
#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 : \n");
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("\nThis is Multiplication of array[i-1] and left[i-1]\n");
for( i = 0 ; i <= x-1 ; i++)
{
printf("Array[%d] = %d , Left[%d] = %d\n",i,array[i],i,left[i]);
}
for( i = x-2 ; i >= 0 ; i--)
{
right[i] = right[i+1] * array[i+1];
}
printf("\nThis is Multiplication of array[i+1] and right[i+1]\n");
for( i = 0 ; i <= x-1 ; i++)
{
printf("Array[%d] = %d , Right[%d] = %d\n",i,array[i],i,right[i]);
}
printf("\nThis is Multiplication of Right[i] * Left[i]\n");
for( i = 0 ; i <= x-1 ; i++)
{
printf("Right[%d] * left[%d] = %d * %d = %d\n",i,i,right[i],left[i],right[i]*left[i]);
}
return 0 ;
}
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.
最近この質問をされましたが、その間にO(N)を取得できませんでしたが、別のアプローチ(残念ながらO(N ^ 2))がありましたが、とにかく共有すると思いました。
最初にList<Integer>
に変換します。
元の配列をarray.length()
回ループします。
while
ループを使用して、次の必要な数のセットを複数設定します。
while (temp < list.size() - 1) {
res *= list.get(temp);
temp++;
}
次に、res
を新しい配列(もちろん前に宣言した)に追加し、array[i]
の値をList
に追加して、以降も同様に続けます。
これはあまり役に立たないことはわかっていますが、インタビューのプレッシャーの下で思いついたものです:)
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;
}
出力:[24、120、60、40、30]
以下は、線形Scala時間の単純なO(n)バージョンです。
def getProductEff(in:Seq [Int]):Seq [Int] = { //この要素の左側にあるすべての要素の積を持つリストを作成します val fromLeft = in.foldLeft((1、Seq.empty [Int]))((ac、i)=>(i * ac._1、ac._2:+ ac._1))._ 2 //この要素の右側にあるすべての要素の積を持つリストを作成します。これは前のステップと同じですが、reverse val fromRight = in.reverseです。 foldLeft((1、Seq.empty [Int]))((ac、i)=>(i * ac._1、ac._2:+ ac._1))._ 2.reverse //index in.indices.map(i => fromLeft(i)* fromRight(i)) } [.____で製品ごとに2つのリストをマージします。]
本質的には、答えはすべての要素の積を左と右に持つ配列であるためです。
これがRubyのワンライナーソリューションです。
nums.map { |n| (num - [n]).inject(:*) }
{- sqrt(n)サブセットを使用した再帰的ソリューション。 O(n)で実行します。 サイズsqrt(n)のsqrt(n)サブセットの解を再帰的に計算します。 次に、各サブセットの積和を再帰的に処理します。 次に、各サブセットの各要素について、 他のすべての製品の積和を使用して積を計算します。 その後、すべてのサブセットが平坦化されます。 実行時の繰り返しはT(n) = sqrt(n)* T(sqrt(n))+ T(sqrt(n)) + n O(n)でT(n)≤cnと仮定します。 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 ) ceiling(sqrt(n))は、sqrt命令が次の場合、バイナリ検索 およびO(logn)反復を使用して計算できることに注意してください。 -} otherProducts [] = [] otherProducts [x] = [1] otherProducts [x、y] = [y、x] otherProducts a = foldl '(++)[] $ zipWith(\ sp-> map(* p)s)solveSubsetsサブセットOtherProducts where n =長さa -サブセットサイズ。 1 <s <n。 s =天井$ sqrt $ fromIntegral n が必要です____。] サブセット= reverse $ loop a [] where loop [] acc = acc loop a acc = loop(drop sa)((take sa):acc)
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("\n Output is {0}",prod);
}
こちらがpythonバージョンです
# 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
さて、このソリューションはC/C++のソリューションと考えることができます。 a [n]のようなn個の要素を含む配列 "a"があるとします。すると、擬似コードは次のようになります。
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];
}
C#を使用した少し機能的な例を次に示します。
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]();
}
}
私は完全に作成されたFuncsの半再帰により、これがO(n)であることを確信していますが、私のテストではO(n)であることを示しているようです時間内に。
Pythonでの私の最初の試み。 O(2n):
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 __== "__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])))
出力:
[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]
O(N)
の問題を解決する別の簡単な概念を次に示します。
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));
これは、Pythonを使用した私の簡潔なソリューションです。
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
Rubyソリューション
a = [1,2,3,4]
result = []
a.each {|x| result.Push( (a-[x]).reject(&:zero?).reduce(:*)) }
puts result
もう1つのソリューション、除算の使用。 2回のトラバーサルで。すべての要素を乗算し、各要素で分割を開始します。
以下にO(n)
スペースとO(n^2)
時間の複雑さを備えたソリューションがありますが、
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;
}
最初にリストからnums[j]
(ここでj != i
)を除外してから、残りの積を取得できます。以下は、このパズルを解くためのpython way
です:
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]
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));
ここに私のコードがあります:
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\n",i,prevproduct*nextproduct);
return prevproduct*a[i];
}
int main()
{
int a[]={2,4,1,3,5};
multiply(a,5,1,0);
return 0;
}
//これはJavaの再帰的なソリューションです// //メインproduct(a、1,0)から次のように呼び出されます;
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)ランタイムを使用した適切なソリューション:
要素iの最終的な配列「結果」を作成し、
result[i] = pre[i-1]*post[i+1];
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])));
}
}
出力:
[360, 240, 180, 144, 120]
時間の複雑さ:O(n)
スペースの複雑さ:O(1)