【问题标题】:I am trying to solve the following problem using C++我正在尝试使用 C++ 解决以下问题
【发布时间】:2022-01-15 12:57:16
【问题描述】:

目标是从给定的整数数组中返回所有相差为 2 的整数对。结果数组应按值的升序排序。假设数组中没有重复的整数。输入数组中整数的顺序无关紧要。

我的代码在这里:

#include <utility>
#include <bits/stdc++.h>
#include <vector>
using namespace std;

std::vector<std::pair<int, int>> twos_difference(const std::vector<int> &vec) {
  vector <int> v1 = vec;
  vector <pair<int,int>> pairs;
  sort(v1.begin(),v1.end(), greater<int>());
  
  for (size_t i=0; i<vec.size()-1; i++){
    pair <int,int> due;
    for (size_t j=1; j<vec.size(); j++){
      if (v1[i] - v1[j] == 2){
        due.first = v1[j];
        due.second = v1[i];
        pairs.push_back(due);
        break;
      }
      
    }
  }
    

  sort(pairs.begin(),pairs.end());

  return pairs;""
}

执行超时(12000 毫秒)为什么??????

【问题讨论】:

  • 您的解决方案是O(n^2)。有一个解决方案是O(n log n)。想一个不同的算法来解决这个问题。
  • 为什么要检查所有元素对(在对输入向量进行排序之后)?当它们的差为 2 时,两个元素可以相距多远?无论如何,“执行超时”似乎来自某些在线法官。为什么?因为我猜你的代码花费了太多时间
  • 这里只是一个初学者:(
  • 你几乎拥有它。对项目进行升序而不是降序排序,然后使内部循环从外部循环的索引开始迭代,直到差值大于 2,然后跳出内部循环,放置一对恰好相差 2 的对(如果有一个) .您需要决定是否输出相同对的多个副本,如果有多个副本,则它们之间用两个分隔,或者您只需要唯一的对。

标签: c++ performance time


【解决方案1】:

我们随时为您提供帮助。

我分析了代码并检查了,这可能是什么问题。

据此,您可以得出改进措施。

请检查下面的列表,也许这会给你和进一步发展的想法。

  1. 您通过引用传递输入向量,然后复制所有数据。没必要做。按原样使用给定的输入向量。当然,除非仍然需要源数据

  2. 您定义了生成的std::vector“pairs”,但不为此保留内存。在此std::vector 上使用push_back 将执行大量内存重新分配和复制。请在“pairs”定义后使用std::pairs.reserve(vec.size()/2);

  3. 无需将“更大”移交给排序功能。排序函数默认会这样做

  4. 不需要双重嵌套循环。您的值已经排序。您可以使用单个循环,然后将 vec[i] 与 [vec[i+1] 进行比较。这会将复杂度从二次降低到线性。

  5. 最后,您再次对这些对进行排序。这不是必需的,因为之前已经对值进行了排序

  6. 请在编译时启用所有优化,例如“发布模式”或“-O3”

请参见下面的示例,该示例首先创建 10.000.000 个随机且唯一的测试值,然后测量操作的执行情况以找到所需的对。

在我的机器上执行时间低于 1 秒。

#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>

#include <random>
#include <unordered_set>
#include <limits>
#include <chrono>
#include <fstream>


constexpr size_t MaxValues = 10'000'000;
std::vector<int> createTestValues() {
    std::random_device rd;      // Will be used to obtain a seed for the random number engine
    std::mt19937 gen(rd());     // Standard mersenne_twister_engine seeded with rd()
    std::uniform_int_distribution<> distrib(std::numeric_limits<int>::min(), std::numeric_limits<int>::max());

    std::unordered_set<int> values{};
    while (values.size() < MaxValues)
        values.insert(distrib(gen));
    return { values.begin(), values.end() };
}

int main() {
    std::vector values = createTestValues();

    auto start = std::chrono::system_clock::now();

    // Main algorithm ------------------------------------------
    std::vector<std::pair<int, int>> result;
    result.reserve(values.size() / 2);
    std::sort(values.begin(), values.end());

    for (size_t k{}; k < values.size() - 1; ++k)
        if (values[k + 1] - values[k] == 2)
            result.push_back({ values[k] , values[k + 1] });
    // ------------------------------------------------------

    auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now() - start);
    std::cout << "Elapsed time: " << elapsed.count() << " ms\n\n";
    std::ofstream ofs{ "test.txt" };
    for (const auto& [v1, v2] : result) ofs << v1 << '\t' << v2 << '\n';
}

【讨论】: