Cho một mảng các số, trả về mảng các sản phẩm của tất cả các số khác (không chia)


186

Tôi đã được hỏi câu hỏi này trong một cuộc phỏng vấn xin việc và tôi muốn biết người khác sẽ giải quyết nó như thế nào. Tôi thấy thoải mái nhất với Java, nhưng các giải pháp trong các ngôn ngữ khác đều được chào đón.

Cho một mảng các số, numstrả về một mảng các số products, products[i]là sản phẩm của tất cả 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]

Bạn phải làm điều này trong O(N)mà không sử dụng phân chia.


49
Câu hỏi này đã được đưa ra một vài lần trong tuần qua hoặc lâu hơn; tất cả các bạn đang phỏng vấn với cùng một công ty? :)
Michael Mrozek

Tôi hiện đang duyệt [interview-questions]thẻ tìm kiếm nó. Bạn có một liên kết nếu bạn tìm thấy nó?
polygenelubricants

2
@Michael: Câu hỏi đó cho phép phân chia. Của tôi rõ ràng cấm nó. Tôi muốn nói rằng họ là hai câu hỏi khác nhau.
polygenelubricants

8
Phân chia thay thế với log (a / b) = log (a) -log (b) và voila!
ldog

1
Hãy tưởng tượng nếu có 1 hoặc nhiều hơn 1 số không trong mảng, bạn sẽ xử lý trường hợp này như thế nào ??
gst

Câu trả lời:


257

Một lời giải thích về phương pháp đa gen là: Thủ thuật là xây dựng các mảng (trong trường hợp cho 4 phần tử)

{              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,  }

Cả hai có thể được thực hiện trong O (n) bằng cách bắt đầu ở cạnh trái và phải tương ứng.

Sau đó nhân hai phần tử mảng với phần tử cho kết quả cần thiết

Mã của tôi sẽ trông giống như thế này:

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];
}

Nếu bạn cần phải là O (1) trong không gian, bạn có thể làm điều này (IMHO ít rõ ràng hơn)

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];
}

4
Đây là thời gian chạy O (n) nhưng nó cũng là O (n) trong độ phức tạp không gian. Bạn có thể làm điều đó trong không gian O (1). Ý tôi là, khác với kích thước của các thùng chứa đầu vào và đầu ra tất nhiên.
wilmustell

8
Rất thông minh! Có một tên cho thuật toán này?
fastcodejava

2
@MichaelAnderson Người đàn ông làm việc tuyệt vời, nhưng xin vui lòng cho tôi biết logic chính đằng sau điều này và làm thế nào bạn bắt đầu điều này một khi bạn nhận được yêu cầu.
ACBalaji

3
Thuật toán sẽ thất bại nếu bất kỳ một trong các phần tử là 0. Vì vậy, đừng quên kiểm tra 0 để bỏ qua.
Mani

2
@Mani Thuật toán vẫn ổn nếu có các phần tử được đặt thành 0. Tuy nhiên, có thể quét đầu vào cho các phần tử đó và hiệu quả hơn nếu chúng được tìm thấy. Nếu có hai phần tử 0, toàn bộ kết quả bằng 0 và nếu chỉ có một phần tử, giả sử v_i=0mục duy nhất khác không trong kết quả là phần tử thứ i. Tuy nhiên, tôi nghi ngờ rằng việc thêm một đường chuyền để phát hiện và đếm các phần tử bằng 0 sẽ làm mất đi sự rõ ràng của giải pháp và có thể không làm tăng hiệu suất thực sự trong phần lớn các trường hợp ..
Michael Anderson

52

Đây là một hàm đệ quy nhỏ (trong C ++) để thực hiện sửa đổi tại chỗ. Nó đòi hỏi O (n) không gian thêm (trên ngăn xếp) mặc dù. Giả sử mảng nằm trong a và N giữ chiều dài mảng, chúng ta có

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;
}

Bất cứ ai có thể giải thích đệ quy này?
nikhil

1
@nikhil Nó đệ quy trước, ghi nhớ các sản phẩm trung gian, cuối cùng tạo thành sản phẩm số cho num[N-1]; sau đó, trên đường trở lại, nó tính toán phần thứ hai của phép nhân được sử dụng để sửa đổi mảng số tại chỗ.
Ja͢ck

Hãy tưởng tượng nếu có 1 hoặc nhiều hơn 1 số không trong mảng, bạn sẽ xử lý trường hợp này như thế nào ??
gst

18

Đây là nỗ lực của tôi để giải quyết nó trong Java. Xin lỗi về định dạng không chuẩn, nhưng mã có rất nhiều sự trùng lặp và đây là cách tốt nhất tôi có thể làm để làm cho nó dễ đọc hơn.

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]"
    }
}

Các bất biến vòng lặp là pi = nums[0] * nums[1] *.. nums[i-1]pj = nums[N-1] * nums[N-2] *.. nums[j+1]. Phần ibên trái là logic "tiền tố" và jphần bên phải là logic "hậu tố".


Đệ quy một lớp

Jasmeet đã đưa ra một giải pháp đệ quy (đẹp!); Tôi đã biến nó thành một lớp lót Java (gớm ghiếc!) Này. Nó thực hiện sửa đổi tại chỗ , với O(N)không gian tạm thời trong ngăn xếp.

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]"

3
Tôi nghĩ rằng vòng lặp 2 biến làm cho nó khó hiểu hơn mức cần thiết (ít nhất là đối với bộ não kém của tôi!), Hai vòng lặp riêng biệt cũng sẽ làm công việc đó.
Guillaume

Đó là lý do tại sao tôi tách mã thành trái / phải, trong nỗ lực cho thấy hai người độc lập với nhau. Tôi không chắc là nó có thực sự hoạt động hay không, mặc dù =)
đa gen

15

Dịch giải pháp của Michael Anderson sang Haskell:

otherProducts xs = zipWith (*) below above

     where below = scanl (*) 1 $ init xs

           above = tail $ scanr (*) 1 xs

13

Lén lút phá vỡ quy tắc "không phân chia":

sum = 0.0
for i in range(a):
  sum += log(a[i])

for i in range(a):
  output[i] = exp(sum - log(a[i]))

2
Nitpick: như xa như tôi biết, máy tính thực hiện logarit sử dụng mở rộng nhị thức của họ - mà không đòi hỏi bộ phận ...

10

Ở đây bạn đi, giải pháp đơn giản và sạch sẽ với độ phức tạp 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]);
    }

6

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));

9
không được phép chia
Michael Anderson

Đó vẫn là một mã tìm kiếm tuyệt vời, mặc dù. Từ chối trách nhiệm rằng nó sử dụng phép chia, tôi vẫn sẽ nêu lên nếu được giải thích.
đa gen

Chết tiệt, tôi đã không đọc câu hỏi thông qua. : s @polygenelubricants giải thích: ý tưởng là thực hiện theo hai bước. Đầu tiên lấy giai thừa của dãy số đầu tiên. Đó là những gì thuật toán tích lũy thực hiện (theo mặc định thêm số, nhưng có thể thực hiện bất kỳ thao tác nhị phân nào khác để thay thế phép cộng, trong trường hợp này là phép nhân). Tiếp theo tôi lặp lại trình tự đầu vào lần thứ hai, biến đổi nó sao cho phần tử tương ứng trong trình tự đầu ra mà giai thừa tôi tính ở bước trước chia cho phần tử tương ứng trong trình tự đầu vào.
wilmustell

1
"giai thừa của chuỗi đầu tiên"? wtf? tôi có nghĩa là sản phẩm của các yếu tố trình tự.
wilmustell

5
  1. Du lịch Trái-> Phải và tiếp tục tiết kiệm sản phẩm. Gọi nó là quá khứ. -> O (n)
  2. Du lịch phải -> trái giữ sản phẩm. Gọi nó là Tương lai. -> O (n)
  3. Kết quả [i] = Quá khứ [i-1] * tương lai [i + 1] -> O (n)
  4. Quá khứ [-1] = 1; và Tương lai [n + 1] = 1;

Trên)


3

Đây là giải pháp của tôi trong C ++ hiện đại. Nó sử dụng std::transformvà khá dễ nhớ.

Mã trực tuyến (Wandbox).

#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 << " "; 
}

2

Đây là O (n ^ 2) nhưng f # rất đẹp:

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]

Tôi không chắc chắn rằng một giải pháp khổng lồ hay giải pháp O (n ^ 2) cho vấn đề O (n) có bao giờ "đẹp".
Nhà vật lý điên

2

Tính toán trước tích của các số ở bên trái và bên phải của mỗi phần tử. Đối với mọi yếu tố, giá trị mong muốn là sản phẩm của các sản phẩm của neig Harbor.

#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;
}

Kết quả:

$ ./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

(CẬP NHẬT: bây giờ tôi nhìn gần hơn, phương pháp này sử dụng cùng một phương pháp như Michael Anderson, Daniel Migowski và đa gen ở trên)


Tên của thuật toán này là gì?
onepiece

1

Khó khăn:

Sử dụng như sau:

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];
}

Vâng, tôi chắc chắn rằng tôi đã bỏ lỡ một số i-1 thay vì i, nhưng đó là cách để giải quyết nó.


1

Ngoài ra còn có một O (N ^ (3/2)) không tối ưu giải pháp . Nó là khá thú vị, mặc dù.

Đầu tiên tiền xử lý mỗi phép nhân một phần kích thước N ^ 0,5 (điều này được thực hiện trong độ phức tạp thời gian O (N)). Sau đó, tính toán cho nhiều giá trị khác của nhiều số có thể được thực hiện trong thời gian 2 * O (N ^ 0,5) (tại sao? Bởi vì bạn chỉ cần nhiều phần tử cuối cùng của các số khác ((N ^ 0,5) - 1), và nhân kết quả với các số ((N ^ 0,5) - 1) thuộc nhóm số hiện tại). Làm điều này cho mỗi số, người ta có thể nhận được thời gian O (N ^ (3/2)).

Thí dụ:

4 6 7 2 3 1 9 5 8

kết quả một phần: 4 * 6 * 7 = 168 2 * 3 * 1 = 6 9 * 5 * 8 = 360

Để tính giá trị của 3, người ta cần nhân các giá trị của các nhóm khác 168 * 360, sau đó với 2 * 1.


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);
    }
}

Giải pháp này tôi đã đưa ra và tôi thấy nó rõ ràng bạn nghĩ gì!?


1
Giải pháp của bạn dường như có độ phức tạp thời gian O (n ^ 2).
Nhà vật lý điên

1
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

mảng = [1, 2, 3, 4, 5] prod = [] Productify (Array, prod, 0) print prod


1

Để được hoàn thành ở đây là mã trong Scala:

val list1 = List(1, 2, 3, 4, 5)
for (elem <- list1) println(list1.filter(_ != elem) reduceLeft(_*_))

Điều này sẽ in ra như sau:

120
60
40
30
24

Chương trình sẽ lọc ra elem hiện tại (_! = Elem); và nhân danh sách mới với phương thức lessLeft. Tôi nghĩ rằng đây sẽ là O (n) nếu bạn sử dụng chế độ xem scala hoặc Iterator cho lười biếng eval.


Mặc dù rất thanh lịch, nhưng nó không hoạt động nếu có nhiều yếu tố có cùng giá trị: val list1 = List (1, 7, 3, 3, 4, 4)
Giordano Scalzo

Tôi đã kiểm tra mã một lần nữa với các giá trị lặp lại. Nó tạo ra 1008 144 112 112 63 63 sau đây Tôi nghĩ rằng nó đúng với phần tử đã cho.
Billz

1

Dựa trên câu trả lời của Billz - xin lỗi tôi không thể nhận xét, nhưng đây là phiên bản scala xử lý chính xác các mục trùng lặp trong danh sách và có thể là 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

trả về:

List(1008, 144, 336, 336, 252, 252)

1

Thêm giải pháp javascript của tôi ở đây vì tôi không tìm thấy ai đề xuất điều này. Cách chia là gì, ngoại trừ đếm số lần bạn có thể trích xuất một số từ một số khác? Tôi đã đi qua tính toán sản phẩm của toàn bộ mảng, và sau đó lặp lại qua từng phần tử và trừ phần tử hiện tại cho đến 0:

//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;
}

1

Tôi đang sử dụng 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;
    }

1

Chúng tôi có thể loại trừ nums[j](nơi j != i) khỏi danh sách trước, sau đó lấy sản phẩm của phần còn lại; Sau đây là một python wayđể giải câu đố này:

from functools import reduce
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]

0

Vâng, giải pháp này có thể được coi là của C / C ++. Hãy nói rằng chúng ta có một mảng "a" chứa n phần tử như [n], sau đó mã giả sẽ như dưới đây.

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];
  }

0

Thêm một giải pháp, Sử dụng phép chia. với hai lần di chuyển ngang. Nhân tất cả các phần tử và sau đó bắt đầu chia nó cho từng phần tử.


0
{-
Giải pháp đệ quy sử dụng tập con sqrt (n). Chạy trong O (n).

Tính toán đệ quy giải pháp trên các tập con sqrt (n) có kích thước sqrt (n). 
Sau đó đệ quy trên tổng sản phẩm của từng tập hợp con.
Sau đó, với mỗi phần tử trong mỗi tập hợp con, nó sẽ tính toán sản phẩm với
tổng sản phẩm của tất cả các sản phẩm khác.
Sau đó làm phẳng tất cả các tập con.

Tái phát trong thời gian chạy là T (n) = sqrt (n) * T (sqrt (n)) + T (sqrt (n)) + n

Giả sử T (n) cn trong 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)

Lưu ý rằng trần (sqrt (n)) có thể được tính bằng cách sử dụng tìm kiếm nhị phân 
và lặp lại O (logn), nếu lệnh sqrt không được phép.
-}

otherSản phẩm [] = []
otherSản phẩm [x] = [1]
otherSản phẩm [x, y] = [y, x]
otherSản phẩm a = Foldl '(++) [] $ zipWith (\ sp -> map (* p) s) đã giải quyếtSubets subsetOther Products
    Ở đâu 
      n = chiều dài a

      - Kích thước tập hợp con. Yêu cầu 1 <s <n.
      s = trần $ sqrt $ từIntegral n

      yetSubets = map other Các tập con
      subsetOther Products = other Products $ tập hợp sản phẩm bản đồ

      tập con = đảo ngược $ loop a []
          trong đó vòng lặp [] acc = acc
                loop a acc = loop (drop sa) ((mất sa): acc)

0

Đây là mã của tôi:

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;
}

0

Đây là một ví dụ chức năng hơi, sử dụng 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]();
                }
            }

Tôi không hoàn toàn chắc chắn rằng đây là O (n), do bán đệ quy của các Func đã tạo, nhưng các thử nghiệm của tôi dường như chỉ ra rằng đó là O (n) đúng lúc.


0

// Đây là giải pháp đệ quy trong Java // Được gọi như sau từ sản phẩm chính (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;
}

0

Một giải pháp gọn gàng với thời gian chạy O (n):

  1. Đối với mỗi phần tử tính toán tích của tất cả các phần tử xảy ra trước đó và nó lưu trữ trong một mảng "trước".
  2. Đối với mỗi phần tử, tính sản phẩm của tất cả các phần tử xảy ra sau phần tử đó và lưu trữ nó trong một mảng "bài"
  3. Tạo một "kết quả" mảng cuối cùng, cho một phần tử i,

    result[i] = pre[i-1]*post[i+1];
    

1
Đây là giải pháp tương tự như được chấp nhận, phải không?
Thomas Ahle

0
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));

0

Đây là một khái niệm đơn giản khác để giải quyết vấn đề 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));

0

Tôi có một giải pháp với sự phức tạp về O(n)không gian và O(n^2)thời gian được cung cấp dưới đây,

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;
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.