【问题标题】:Maximum product C++最大积 C++
【发布时间】:2020-10-05 19:29:29
【问题描述】:

我得到了一些负数和正数的数组。 我应该找到通过将数组中的 2 个相邻数字相乘获得的最大乘积。 这是我写的代码:

 #include <vector>
#include <iostream>
using namespace std; 
int adjacentElementsProduct(vector<int> inputArray) 
  {
      for(int i = 0; i < inputArray.size(); i++) {
      if((inputArray[i] * inputArray[i+1])>(inputArray[i+1] * inputArray[i+2])) {
        std::cout << inputArray[i] * inputArray[i+1] << "\n";
       }  else  if((inputArray[i+1] * inputArray[i+2])>(inputArray[i+2] * inputArray[i+3])) {
           std::cout << inputArray[i+1] * inputArray[i+2] << "\n";
           } else if((inputArray[i+2] * inputArray[i+3])>(inputArray[i+3] * inputArray[i+4])) {
               std::cout << inputArray[i+2] * inputArray[i+3] << "\n";
               } else if((inputArray[i+3] * inputArray[i+4])>(inputArray[i+4] * inputArray[i+5])) {
                   std::cout << inputArray[i+3] * inputArray[i+4] << "\n";
                   } else {
           std::cout << "Unknow" << "\n";
       } return 1;
      }
  }

int main() {
  adjacentElementsProduct({5, 8});
  adjacentElementsProduct({1,2,3});
  adjacentElementsProduct({1,5,10,9});
  adjacentElementsProduct({5,1,2,3,1,4});
  adjacentElementsProduct({4,12,3,1,5});
  adjacentElementsProduct({3,6,-2,-5,7,3});
  adjacentElementsProduct({9, 5, 10, 2, 24, -1, -48});
  adjacentElementsProduct({5, 6, -4, 2, 3, 2, -23});
  adjacentElementsProduct({-23, 4, -5, 99, -27, 329, -2, 7, -921});
  adjacentElementsProduct({1,0,1,0,1000});
  adjacentElementsProduct({1,2,3,0});
  return 1 ;
}

输出:

40
6
90
5
48
18
50
30
-20
Unknow
6

代码只比较了 inputArray[i] * inputArray[i+1] 和 inputArray[i+1] * inputArray[i+2] 的乘积但是我想在数组中的所有数字中找到最大的乘积。

【问题讨论】:

  • 我没看懂。那么你需要找到相邻元素或所有元素的最大乘积吗?
  • 我需要找到数组中所有相邻元素的最大乘积。
  • @PooryaKeshavarzi -- 如果向量有 1000 个元素怎么办?我确定你不想写 2000 行代码。
  • 您的代码表现出未定义的行为。您的循环将允许i 到达inputArray.size()-1,此时inputArray[i+1] 是一个越界数组访问。你写了一个循环,所以使用它。 (另外,请考虑更合理的缩进。通常else 的缩进级别与对应的if 相同。)

标签: c++ algorithm vector max


【解决方案1】:

您想遍历输入向量并计算相邻元素的乘积。 然后,您想找到这些产品中的最大值。您不需要所有硬编码的[i+1], [i+2], [i+3], ... 恶作剧,您已经有了可以为您获取所有这些数字的东西——for 循环。

int adjacentElementsProduct(vector<int> inputArray) 
{
      // Set initial max product to a very small number so that 
      // it is always replaced by our first product
      int maxProduct = std::numeric_limits<int>::min();
      for(int i = 0; 
            i < inputArray.size() - 1;  /* because we will be doing i + 1 inside the loop */
            i++) {
          // Calculate product of this and next element
          int product = inputArray[i] * inputArray[i + 1];
          
          if (product > maxProduct) 
              maxProduct = product; // This product is the greatest so far,  
                                    // so keep it and get rid of the old max.
      }
      return maxProduct;
}

为了解释它是如何工作的,让我们看一下函数的执行示例输入。假设我们做adjacentElementsProduct({5,1,2,3,1,4});

  1. maxProduct 设置为某个非常大的负数(比如 -99999999)
  2. inputArray.size() 是 6。inputArray.size() - 1 是 5。
  3. i = 0。是0 &lt; 5?是的。进入循环
    1. product = inputArray[0] * inputArray[1] = 5
    2. 5 &gt; maxProduct (-99999999)?是的。设置maxProduct = 5
    3. i 增加到 1。
  4. i = 1。是1 &lt; 5?是的。进入循环
    1. product = inputArray[1] * inputArray[2] = 2
    2. 2 &gt; maxProduct (5)?没有。
    3. i 增加到 2。
  5. i = 2。是2 &lt; 5?是的。进入循环
    1. product = inputArray[2] * inputArray[3] = 6
    2. 6 &gt; maxProduct (5)?是的。设置maxProduct = 6
    3. i 增加到 3。
  6. i = 3。是3 &lt; 5?是的。进入循环
    1. product = inputArray[3] * inputArray[4] = 3
    2. 3 &gt; maxProduct (6)?没有。
    3. i 增加到 4。
  7. i = 4。是4 &lt; 5?是的。进入循环
    1. product = inputArray[4] * inputArray[5] = 4
    2. 4 &gt; maxProduct (6)?没有。
    3. i 增加到 5。
  8. i = 5。是5 &lt; 5?没有。
  9. 返回maxProduct,即6。

【讨论】:

  • int maxProduct = -9999999; -- int maxProduct = std::numeric_limits&lt;int&gt;::min();
  • @PaulMcKenzie 谢谢! -999999 是一个占位符,直到我查看文档以了解 numeric_limits 的名称!
  • 嘿。谢谢。你能解释一下你的部分吗?
  • if (product &gt; maxProduct) 只有在当前两项的乘积大于我们目前遇到的最大乘积时才会输入,即当前乘积是新的最大值,所以我们将它的值写入maxProduct变量@PooryaKeshavarzi
  • @NathanPierson 我只是在使用已经存在于 OP 问题中的循环。我认为在答案中添加更多内容会不必要地混淆 OP。
【解决方案2】:

我认为你的功能是矫枉过正。您可以使用 running 最大值来做到这一点:

const unsigned int length = inputArray.length();
int maximum = inputArray[0] * inputArray[1];
for (unsigned int i = 1U; i < (length - 1U); ++i)
{
    const int product = inputArray[i] * inputArray[i + 1];
    if (product > maximum) maximum = product;
}

这可以进一步优化,但这是 OP 的练习。

编辑 1:通过指针
这可能更理想,但只有汇编语言会告诉(或分析):

const unsigned int length = inputArray.length();
int const * p_first = &inputArray[0];
int const * p_second = &inputArray[1];
int maximum = (*p_first++) * (*p_second++);
for (unsigned int i = 1u; i < (length - 1); ++i)
{
    int product = (*p_first++) * (*p_second++);
    if (product > maximum) maximum = product;
}

在上面的代码片段中,两个数组位置是在指针中维护的。指针可以保存在寄存器中。无需每次计算循环内的偏移量。递增指针操作简单快捷。一些处理器具有可以取消引用指针并在单个指令中递增的指令。一些编译器可能会根据优化设置执行此优化。

编辑 2:跟踪以前的值
另一个优化是通过记住数组中的前一个值来减少大约一半的内存访问:

const unsigned int length = inputArray.length();
int previous = inputArray[0];
int next     = inputArray[1];
int maximum  = previous * next;
previous = next;
for (unsigned int i = 1u; i < length; ++i)
{
    next = inputArray[i];
    const int product = previous * next;
    if (product > maximum) maximum = product;
    previous = next;
}

在上面的代码片段中,之前的数组值被记住在一个变量中。这消除了访问数组以获取先前值的需要;只需要一次数组访问。

编译器可能在更高的优化级别上执行此优化。证明是比较变量片段的汇编语言。

【讨论】:

    【解决方案3】:

    &lt;numeric&gt; 中有一个算法可以为您执行此操作:

    int adjacentElementsProduct(std::vector<int> const & inputArray) 
    {
      // [[assert: inputArray.size > 1 ]]
    
      return std::inner_product(inputArray.begin(), inputArray.end() - 1,
                                inputArray.begin() + 1, 
                                0, 
                                [](int i, int j) { return std::max(i, j); }, 
                                std::multiplies{});
    }
    

    它的效率和可读性差不多。

    【讨论】:

    • 感谢您的帮助但我对编码还很陌生所以我用更简单的东西来做。无论如何谢谢
    • @PooryaKeshavarzi 好的,这取决于你。 IMO,这个解决方案比使用原始循环更容易理解。
    【解决方案4】:

    对于初学者,该函数不应输出任何消息。由函数的调用者决定是否输出消息。

    该函数应返回一个迭代器或一对迭代器,它们指向具有最大乘积的两个相邻元素。

    至于您的函数实现,它具有未定义的行为,因为它可以访问向量中不存在的元素。

    我可以建议以下函数定义,如下面的演示程序所示。

    #include <iostream>
    #include <utility>
    #include <vector>
    #include <iterator>
    
    std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator>
    adjacentElementsProduct( const std::vector<int> &v )
    {
        std::pair<std::vector<int>::const_iterator, std::vector<int>::const_iterator> 
        p = { std::begin( v ), std::end( v ) };
    
        if (not ( v.size() < 2 ))
        {
            p.second = std::next( std::begin( v ) );
            long long int max_product = static_cast<long long int>( *p.first ) * *p.second;
    
            for (auto prev = p.second, current = std::next( p.second );
                current != std::end( v );
                std::advance( prev, 1 ), std::advance( current, 1 ))
            {
                if (max_product < static_cast<long long int>( *prev ) * *current)
                {
                    p = { prev, current };
                }
            }
        }
    
        return p;
    }
    
    int main()
    {
        std::vector<int> v = { 5, 8 };
        auto p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 1,2,3 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 1,5,10,9 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 5,1,2,3,1,4 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 4,12,3,1,5 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 3,6,-2,-5,7,3 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 9, 5, 10, 2, 24, -1, -48 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 5, 6, -4, 2, 3, 2, -23 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { -23, 4, -5, 99, -27, 329, -2, 7, -921 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 1, 0, 1, 0, 1000 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    
        v = { 1,2,3,0 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( *p.first ) * *p.second << '\n';
    }
    

    程序输出是

    40
    6
    90
    6
    48
    21
    48
    30
    -14
    0
    6
    

    如果你还不知道迭代器,那么可以通过以下方式定义函数

    #include <iostream>
    #include <utility>
    #include <vector>
    
    std::pair<std::vector<int>::size_type, std::vector<int>::size_type>
    adjacentElementsProduct( const std::vector<int> &v )
    {
        std::pair<std::vector<int>::size_type, std::vector<int>::size_type>
        p = { 0, v.size() };
    
        if (not ( v.size() < 2 ))
        {
            p.second = 1;
            long long int max_product = static_cast<long long int>( p.first ) * p.second;
    
            for (std::vector<int>::size_type i = 3; i < v.size(); i++ )
            {
                if (max_product < static_cast<long long int>( v[i - 1] ) * v[i] )
                {
                    p = { i - 1, i };
                }
            }
        }
    
        return p;
    }
    
    int main()
    {
        std::vector<int> v = { 5, 8 };
        auto p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 1,2,3 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 1,5,10,9 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 5,1,2,3,1,4 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 4,12,3,1,5 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 3,6,-2,-5,7,3 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 9, 5, 10, 2, 24, -1, -48 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 5, 6, -4, 2, 3, 2, -23 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { -23, 4, -5, 99, -27, 329, -2, 7, -921 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 1, 0, 1, 0, 1000 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    
        v = { 1,2,3,0 };
        p = adjacentElementsProduct( v );
        std::cout << static_cast< long long int >( p.first ) * p.second << '\n';
    }
    

    【讨论】:

    • 谢谢。但我现在不明白你的代码,因为我真的很新但无论如何谢谢我自己做的
    • @PooryaKeshavarzi 查看我更新的帖子。至于你的解决方案,那我肯定是错的。:)
    猜你喜欢
    • 2019-11-05
    • 2013-09-20
    • 1970-01-01
    • 1970-01-01
    • 2013-07-30
    • 2020-07-24
    • 1970-01-01
    • 1970-01-01
    • 2012-10-17
    相关资源
    最近更新 更多