【问题标题】:Puzzle.. solving product of values in array X谜题..解决数组 X 中值的乘积
【发布时间】:2010-10-30 07:27:41
【问题描述】:

你能帮我解决这个问题吗?

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

基本的 - O(n^2) 和一个使用除法的很容易。但我就是找不到比 O(n^2) 更快的解决方案。

【问题讨论】:

  • 你能重新表述一下这个问题吗?不知道为什么需要除法……是求累积积吗?
  • 这个问题通常要求在 O(n) 内完成,无需除法。
  • 请注意,如果列表包含零,则使用除法不起作用。

标签: algorithm puzzle


【解决方案1】:

left[i]X 中所有元素的乘积,来自1..i。让right[i]X 中所有元素的乘积,来自i..N。您可以通过以下方式计算O(n) 中的两者而不进行除法:left[i] = left[i - 1] * X[i]right[i] = right[i + 1] * X[i];

现在我们将计算 M: M[i] = left[i - 1] * right[i + 1]

注意:leftright 是数组。

希望清楚:)

【讨论】:

  • 您或许可以补充一点,leftright 是数组。
  • @Svante 好的,我会补充:)
  • 嗨皮塔尔。我很难理解您的解决方案。你能再解释一下吗?
  • @ebae 嗨!您希望 M[i] 是 X 中除第 i 个元素之外的所有元素的乘积。所以让left[i] = X 中所有索引right[i] = X 中所有索引> i 的元素的乘积。然后 M[i] = 左[i] * 右[i]。我已经在上面描述了如何在线性时间内预先计算 leftright 数组。
  • 嗯,Petar,是不是该解决方案的运行时间应该比 O(n^2) 好?您的解决方案在商定的 O(n) 时间内解决 M[i]。现在,如果要填充 M,则必须执行 O(n^2)。这太慢了。对吗?
【解决方案2】:

这里有一个 Python 解决方案。我用除法的简单方法来与没有除法的困难方法进行比较。我能得到这份工作吗?

L = [2, 1, 3, 5, 4]

prod = 1
for i in L: prod *= i
easy = map(lambda x: prod/x, L)
print easy

hard = [1]*len(L)
hmm = 1
for i in range(len(L) - 1):
    hmm *= L[i]
    hard[i + 1] *= hmm
huh = 1
for i in range(len(L) - 1, 0, -1):
    huh *= L[i]
    hard[i - 1] *= huh
print hard

【讨论】:

  • 如果列表包含零,则除法方法将失败。
【解决方案3】:

O(n) - http://nbl.cewit.stonybrook.edu:60128/mediawiki/index.php/TADM2E_3.28

两次传球-

 int main (int argc, char **argv) {
    int array[] = {2, 5, 3, 4};
    int fwdprod[] = {1, 1, 1, 1};
    int backprod[] = {1, 1, 1, 1};
    int mi[] = {1, 1, 1, 1};
    int i, n = 4;
    for (i=1; i<=n-1; i++) {
        fwdprod[i]=fwdprod[i-1]*array[i-1];
    }
    for (i=n-2; i>=0; i--) {
        backprod[i] = backprod[i+1]*array[i+1];
    }
    for (i=0;i<=n-1;i++) {
        mi[i]=fwdprod[i]*backprod[i]; 
    }
    return 0;
}

【讨论】:

    【解决方案4】:

    老但很酷,我自己在一次采访中被问到这个问题并看到了几个解决方案,但这是我最喜欢的,取自 http://www.polygenelubricants.com/2010/04/on-all-other-products-no-division.html

    static int[] products(int... nums) {
           final int N = nums.length;
           int[] prods = new int[N];
           java.util.Arrays.fill(prods, 1);
           for (int // pi----> * <----pj
              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   ;
              System.out.println("pi up to this point is " + pi + "\n");
              System.out.println("pj up to this point is " + pj + "\n");
              System.out.println("prods[i]:" + prods[i] + "pros[j]:" +  prods[j] + "\n");
           }
           return prods;
        }
    

    这是怎么回事,如果你写出所有迭代的 prods[i],你会看到正在计算以下内容

    prods[0], prods[n-1]
    prods[1], prods[n-2]
    prods[2], prods[n-3]
    prods[3], prods[n-4]
    .
    .
    .
    prods[n-3], prods[2]
    prods[n-2], prods[1]
    prods[n-1], prods[0]
    

    所以每个 prods[i] 被击中两次,一次是从头到尾,一次是从头到尾,这两次迭代都在累积产品,因为它们 向中心移动,所以很容易看到我们会得到我们需要的东西,我们只需要小心并看到它错过了元素本身,这就是 它变得棘手。关键在于

    pi *= nums[i++], pj *= nums[j--]
    

    在 for 循环条件本身中而不是在主体中,直到结束才发生 迭代。因此对于 prods[0], 它从 1*1 开始,然后 pi 设置为 120,因此 prods[0] 错过了第一个元素 prods[1], 是 1 * 120 = 120 然后 pi 设置为 120*60 等等等等

    【讨论】:

      【解决方案5】:

      O(nlogn) 方法:

      int multiply(int arr[], int start, int end) {
          int mid;
          if (start > end) {
              return 1;
          }
          if (start == end) {
              return arr[start];
          }
          mid = (start+end)/2;
          return (multiply(arr, start, mid)*multiply(arr, mid+1, end));
      }
      
      int compute_mi(int arr[], int i, int n) {
          if ((i >= n) || (i < 0)) {
              return 0;
          }
      
          return (multiply(arr, 0, i-1)*multiply(arr, i+1, n-1));
      }
      

      【讨论】:

        【解决方案6】:

        这是我在 Python 中的解决方案:方法简单但计算成本可能很高?

        def product_list(x):
        ans = [p for p in range(len(x))]
        for i in range(0, len(x)):
            a = 1
            for j in range(0, len(x)):
                if i != j:
                    a = a*x[j]
                ans[i] = a
        return ans
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-13
          • 2013-11-29
          • 1970-01-01
          相关资源
          最近更新 更多