【问题标题】:Interview - finding even sum pair in an array面试 - 在数组中找到偶数对
【发布时间】:2016-06-01 09:17:58
【问题描述】:

给定一个数组,如何返回总和为偶数的对数?

例如:

a[] = { 2 , -6 , 1, 3, 5 }

在这个数组中,与偶数配对的 nos 是 (2,-6), (1,3) , (1,5), (3,5)

函数应该返回 4,因为有 4 对,如果没有,则返回 -1。

预期时间复杂度 - O(N) 最坏情况 预期空间复杂度 - O(N) 最坏情况

方法一: 蛮力

Start with the first number
  Start with second number
      assign the sum to a temp variable
      check if the temp is even
          If it is increment evenPair count
      else
          increment the second index

这里的时间复杂度是O(N2)

【问题讨论】:

  • 如果两个数都是偶数或都是奇数,两个数之和将是一个偶数,因此您应该能够通过简单地计算数组中奇数和偶数的数量以及从有可能的有效对数。如果你想要的只是对的数量,你实际上不需要做所有的加法。
  • 但是如果你不添加它们如何找到可能的对呢?
  • @JonathanPotter 您实际上可以将其发布为答案!
  • @aba123 只需按顺序计算奇数和偶数。然后您可以使用著名的数学公式 (n!/2!* (n - 2)!) 来计算总和的数量。例如,如果一个序列中有 n = 4 个偶数,那么将有 6 个偶数和等等。
  • 数字是否重复?示例:{1,2,3,2,1}

标签: c++ c arrays


【解决方案1】:
int odd = 0, even = 0;
for (int i = 0; i < n; i++) {
    if (a[i] % 2 == 0) {
        even++;
    } else {
        odd++;
    }
}
int answer = (odd * (odd - 1) + even * (even - 1)) / 2;

【讨论】:

    【解决方案2】:

    如果 a 和 b 是偶数,则 a + b 是偶数。
    如果它们是奇数,则 a + b 也是偶数。
    如果一个是奇数一个是偶数,a + b 是奇数。

    这意味着我们不需要执行任何加法,我们只需要知道每种数字有多少。
    找出这一点需要线性时间。

    如果您有 k 个数字,则有 k - 1 对包含第一个数字,k - 2 对包含第二个数字,依此类推。
    使用熟悉的求和公式,sum(1 .. n) = (n * (n + 1)) / 2

    ne = number of even numbers
    no = number of odd numbers
    

    那么,

    number of pairs = (ne-1) * ne / 2 + (no-1) * no / 2 
                    = ((ne-1)*ne + (no-1)*no) / 2
    

    该计算在恒定时间内运行,因此时间复杂度仍然是线性的。

    而且我们只需要恒定数量的额外空间,这比要求要好。


    可能值得思考的后续面试问题:

    如果出现以下情况,复杂性(时间和空间)会发生什么:

    • 重复只计算一次,即{1,1,1,2}只有两个这样的对?
    • 我们不考虑顺序,即(1,2)(2,1) 是“同一对”吗?

    【讨论】:

      【解决方案3】:

      如果使用标准算法,那么代码可以如下所示

      #include <iostream>
      #include <utility>
      #include <numeric>
      #include <iterator>
      
      int main() 
      {
          int a[] = { 2 , -6 , 1, 3, 5 };
      
          typedef size_t Odd, Even;
          auto p = std::accumulate( std::begin( a ), std::end( a ), 
                                    std::pair<Odd, Even>( 0, 0 ),
                                    []( std::pair<Odd, Even> &acc, int x )
                                    {
                                      return x & 1 ? ++acc.first : ++acc.second, acc;
                                    } );
      
          std::cout << "There are " 
                    << ( p.first * ( p.first - 1 ) + p.second * ( p.second - 1 ) ) / 2
                    << " even sums" << std::endl;
      
          return 0;
      }
      

      输出是

      There are 4 even sums
      

      考虑到n! / ( 2! * ( n - 2 )! ) 等价于( n - 1 ) * n / 2

      使用标准算法的优点是您可以使用序列的任何子范围。您也可以使用标准流输入,因为std::accumulate 使用输入迭代器。

      如果在赋值的描述中写下如果数组元素之间没有偶数和,函数应该返回 0 而不是 -1 会更好。

      在面试中展示这段代码并不可耻,尽管我建议永远不要在面试中做任何作业。面试不是考试。

      【讨论】:

        【解决方案4】:

        另一种方法是通过偶数和奇数计算总和的数量,然后再相加

        int sumO = 0 , sumE = 0 , numO = 0 , numE = 0;
        for (int i=0; i < 5; i++)
        {
            if (a[i] % 2 == 0)
            {
                sumE += numE;
                numE ++;
            }
            else
            {
                sumO += numO;
                numO ++;
            }
        }
        
        printf ("Total: %d\n", sumO + sumE);
        

        【讨论】:

          【解决方案5】:

          我在一次采访中得到了这个问题。 无需将偶数和奇数分开。

          public static int evenTotalPairs(int[] A) {
          int size = A.length;
          int evens = 0;
          for(int i = 0; i < size; i++ ){
              if(A[i] % 2 == 0){
                  evens++;
              }
          }
          return evens*(evens-1)/2 + (size-evens)*(size-evens-1)/2;
          

          }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2020-05-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-02-27
            • 2021-05-22
            相关资源
            最近更新 更多