除了数组的一个成员之外,是否有其他方法可以执行操作?

时间:2018-11-08 15:27:36

标签: c#

我一直在解决日常编码问题,并来到了这个问题。

  

给出一个整数数组,返回一个新数组,使每个元素   在新数组的索引i处是所有数字的乘积   原始数组,除了i处的那个。

     

例如,如果我们的输入是[1、2、3、4、5],则预期输出   会是[120,60,40,30,24]。如果我们的输入是[3,2,1],则   预期输出为[2、3、6]。   后续:如果无法使用除法怎么办?

因此,执行此操作的简单方法是将数组中的所有元素相乘,然后除以[i],但这带来的问题是,如果I = 0,您将得到一个 错误。

我知道 aggregate 函数,该函数对数组的所有成员执行操作,但是有一种方法可以修改 aggregate ,使其对< em>除一个成员外的所有成员,或者是否存在其他提供此功能的函数/方法?

2 个答案:

答案 0 :(得分:5)

如果source小,则可以在Where的帮助下跳过索引,例如

  int[] source = new int[] { 1, 2, 3, 4, 5 };

  int[] result = Enumerable
    .Range(0, source.Length)
    .Select(i => source
       .Where((value, index) => index != i) // all items except i-th
       .Aggregate((s, a) => s * a))         // should be multiplied 
    .ToArray();

  Console.Write(string.Join(", ", result));

结果:

  120, 60, 40, 30, 24

编辑:但是,该解决方案的时间复杂度为O(N**2);如果初始source数组为 large ,我们可以实现更有效的O(N)代码(是的,我们应该注意 zeroes ):

  int[] source = ...

  int[] result;

  int zeroCount = source.Count(item => item == 0);

  if (zeroCount >= 2)      // All zeroes case
    result = new int[source.Length];   
  else if (zeroCount == 1) // All zeroes save one value case
    result = source
      .Select(v => v == 0
         ? source.Where(item => item != 0).Aggregate((s, a) => s * a)
         : 0)
      .ToArray(); 
  else {                   // No zeroes case
    // long, 1L: to prevent integer overflow, e.g. for {1000000, 1000000} input
    long total = source.Aggregate(1L, (s, a) => s * a);

    result = source
      .Select(v => (int)(total / v)) // yes, it's a division...
      .ToArray(); 
  }

答案 1 :(得分:3)

除了单个指定的成员(没有,是按值还是按索引指定它?)上,没有所有内建函数可以聚合。

但是,循环将非常简单,Linq为您提供了Where方法,您可以在其中创建任意谓词,然后可以将聚合应用于过滤后的< / em>结果。

例如,要对一个数组的所有数字求和而不是对第三个数字求和,可以执行以下操作:

array.Where((x,i) => i != 2).Sum();  // use 2 since the index is 0-based

Product也没有内置的Linq方法,但是我敢肯定那里有一个方法,否则您也可以轻松地自己动手。