Algorithm 算法设计手册中数据结构实践的最佳解决方案

Algorithm 算法设计手册中数据结构实践的最佳解决方案,algorithm,data-structures,solution,Algorithm,Data Structures,Solution,此问题摘自《算法设计手册》,3-28。 问题是: 您有一个由n个整数组成的无序数组X。查找包含n个元素的数组M,其中M_i是X中除X_i以外的所有整数的乘积。您可以不使用除法,也可以使用额外的内存。(提示:存在比O(n^2)更快的解决方案 有人有什么好主意吗?O(n)解决方案: 计算数组A,使A_i是X_1..X_i的乘积 计算数组B,使B_i是X_i..X_n的乘积(相反,即从数组索引n开始) 然后将M计算为M_i=A_(i-1)*B_(i+1) 步骤1和2可以通过使用在先前迭代中计算的子过程

此问题摘自《算法设计手册》,3-28。
问题是:

您有一个由n个整数组成的无序数组X。查找包含n个元素的数组M,其中M_i是X中除X_i以外的所有整数的乘积。您可以不使用除法,也可以使用额外的内存。(提示:存在比O(n^2)更快的解决方案

有人有什么好主意吗?

O(n)解决方案:

  • 计算数组A,使A_i是X_1..X_i的乘积
  • 计算数组B,使B_i是X_i..X_n的乘积(相反,即从数组索引n开始)
  • 然后将M计算为M_i=A_(i-1)*B_(i+1)
  • 步骤1和2可以通过使用在先前迭代中计算的子过程在O(n)中计算

    [当然,处理索引转义数组边界的拐角情况!]

    编辑:为了清晰起见,我在下面提供完整的解决方案

  • 将数组A计算为:A_1=X_1;对于(2..N)中的i:A_i=A_(i-1)*X_i
  • 将数组B计算为:B_n=X_n;对于(n..2)中的i:B_i=B_(i+1)*X_i
  • 计算数组M为:M_1=B_2;M_n=A_(n-1);对于(2..(n-1))中的i:M_i=A_(i-1)*B_(i+1)

  • 只需使用一个数组和两个循环,一个循环是从前端到后端,另一个循环是从后端到后端

    b[0] =      a[1]*a[2]*a[3]*a[4]
    b[1] = a[0]*     a[2]*a[3]*a[4]
    b[2] = a[0]*a[1]*     a[3]*a[4]
    b[3] = a[0]*a[1]*a[2]*     a[4]
    b[4] = a[0]*a[1]*a[2]*a[3]
    
    代码如下:

    void solve(int arr[], int len){
        int index = 0;
    
        // loop from begin to end
        arr_b[0] = 1;
        for (index = 1; index < len; ++index){
            arr_b[index] = arr_b[index - 1]*arr_a[index - 1]; 
        }
    
        // loop from end to begin
        for (index = len-2; index > 0; --index){
            arr_b[0] *= arr_a[index + 1];
            arr_b[index] *= arr_b[0];
        }
        arr_b[0] *= arr_a[1];
    }
    
    void solve(int-arr[],int-len){
    int指数=0;
    //自始至终循环
    arr_b[0]=1;
    对于(索引=1;索引0;--索引){
    arr_b[0]*=arr_a[index+1];
    arr_b[index]*=arr_b[0];
    }
    arr_b[0]*=arr_a[1];
    }
    
    还需要初始化A_0=1和B_{n+1}=1来处理M_0和M_n的角情况。是的,刚刚添加了一个提及角情况的编辑。您可以计算A[],使A[1]为1,然后A[i]为2..n为X[i-1]*A[i-1]并将其存储在M[](向前)中,然后计算B[],使B[n]为1,然后B[i]为n-1..1为X[i+1]*B[i]在飞行中直接乘以“M[]”(向后)?@gmch很好的优化-您已经证明,除了输出阵列之外,只需恒定的额外空间就可以解决它。我的目标只是在线性时间内解决这个问题。