【问题标题】:Given a set N of integers and an integer y, determine if there two elements exist in N whose absolute difference is equal to y给定一组整数 N 和一个整数 y,判断 N 中是否存在两个绝对差等于 y 的元素
【发布时间】:2016-01-23 06:30:47
【问题描述】:

我遇到了这个问题,我被困在这个问题上。它说,

给定一组整数 N 和一个整数 y,判断是否存在 N 中绝对差等于 y 的两个元素,并且 打印这些数字。该算法应该花费 O(n lg n) 时间。 证明你的算法在 O(n lg n) 时间内运行的原因。例如令 N= 3 , 7, 2, 1, 4, 10 y = 1 N 中有三对元素 绝对差是 1 对 1 = |3 - 2| = |-1| = 1 对 2 = |3 - 4|= |-1| = 1 对 3 = |2 -1| = 1

我在 C++ 中进行了如下尝试,但它不能处理所有边界情况,例如上例中的 if y=8,它不打印任何内容,但应该打印 (2,10)。

vector<int> printPairs(vector<int> N1, vector<int> N2, int y){
    int a = 0, b = 0;
    vector<int> result;
    while (a < N1.size() && b < N2.size()){
        if (N1[a] < N2[b]){
            result.push_back(N1[a]);
            if (abs(N1[a] - N2[b]) == y)
                cout << "(" << N1[a] << "," << N2[b] << ")" << endl;
            a++;
        }
        else {
            result.push_back(N2[b]);
            if (abs(N1[a] - N2[b]) == y)
                cout << "(" << N1[a] << "," << N2[b] << ")" << endl;
            b++;
        }
    }
    while (a < N1.size())
        result.push_back(N1[a++]);
    while (b < N2.size()){
        result.push_back(N2[b++]);
    }
    return result;
}
vector <int> getPairs(vector<int> N, int y){
    if (N.size() == 1)
        return N;
    vector <int> firstHalf = getPairs(vector<int>(N.begin(), N.begin() + N.size() / 2), y);
    vector <int> secondHalf = getPairs(vector<int>(N.begin() + ceil(N.size() / 2), N.end()), y);
    return printPairs(firstHalf, secondHalf, y);
}

【问题讨论】:

    标签: c++ arrays algorithm


    【解决方案1】:

    使用 std::set 容器。

    std::set::find() 的时间复杂度是 O(logN)。

    调用 N 次 find() 会花费你 O(NlogN)。

    代码示例:

    #include <iostream>
    #include <set>
    
    int main() {
      std::set<int> values = {3, 7, 2, 1, 4, 10};
      int y = 1;
      for (int elem : values) {
        if (values.find(elem + y) != values.end()) {
          std::cout << elem << " " << elem + y << std::endl;
        }
      }
      return 0;
    }
    

    输出:

    1 2
    2 3
    3 4
    

    另一种算法:

    1. 对元素进行排序 (NlogN)

    2. 对每个元素使用二进制搜索(logN 每个搜索查询)。

    例子:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main() {
      std::vector<int> values = {3, 7, 2, 1, 4, 10};
      int y = 1;
      std::sort(values.begin(), values.end());
      for (int i = 0; i + 1 < values.size(); ++i) {
        if (std::binary_search(
              values.begin() + i + 1, values.end(), values[i] + y)) {
          std::cout << values[i] << " " << values[i] + y << std::endl;
        }
      }
      return 0;
    }
    

    输出:

    1 2
    2 3
    3 4
    

    或者您可以通过使用两个指针的想法将步骤 2 简化为 O(N):

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    int main() {
      std::vector<int> values = {3, 7, 2, 1, 4, 10};
      int y = 1;
      std::sort(values.begin(), values.end());
      int l = 0, r = 0;
      for (int i = 0; i + 2 < 2 * values.size(); ++i) {
        if (r + 1 < values.size() &&
            values[r] - values[l] <= y) {
          ++r;
        } else {
          ++l;
        }
        if (values[l] + y == values[r]) {
          std::cout << values[l] << " " << values[r] << std::endl;
        }
      }
      return 0;
    }
    

    总复杂度相同(但算法会快一点):O(NlogN) + O(N) = O(NlogN)

    【讨论】:

    • 这真的很有帮助!非常感谢!
    • 你在作弊:你忽略了将数字放入容器的成本,即O(n log n) 的集合!实际上,您首先对输入进行排序,这也是我会采用的方法。
    • 这不是作弊。排序的成本是 O(n log n)。这只会增加搜索成本,也就是 n 倍 log n。因此总成本将是 2*n log n,其渐近符号等于 O(n log n)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-27
    • 2019-11-23
    • 1970-01-01
    相关资源
    最近更新 更多