提问者:小点点

我如何优化代码以返回最接近给定整数的数字,而不在给定列表中?


我解决了这个问题陈述(耶耶,我知道,我正在把问题陈述放在下面)。

给出了一个整数X和一个长度为n的整数序列:p1,…,pn。 在序列p1,…,pN中不包含的整数中(不一定是正的),求出离X最近的整数,即与X的绝对差值最小的整数。 如果有多个这样的整数,报告最小的这样的整数

这是我使用的代码:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>

int main() {
    int x = 0;
    int n = 0;
    std::cin >> x >> n;
    std::vector<decltype(x)> vect(n);
    bool vect_contains_x = false;
    for (auto& elem : vect) {
        std::cin >> elem;
        if (elem == x) {
            vect_contains_x = true;
        }
    }
    int num = 0;
    if (!vect_contains_x) {
        num = x;
    }
    else {
        std::sort(vect.begin(), vect.end());
        while (1) {
            static int i = 1;
            if (std::find(vect.begin(), vect.end(), x - i) == vect.end()) {
                num = x - i;
                break;
            }
            else if (std::find(vect.begin(), vect.end(), x + i) == vect.end()) {
                num = x + i;
                break;
            }
            else {
                i += 1;
            }
        }
    }
    std::cout << num << "\n";
    return 0;
}

此代码在13-18ms中呈现结果。

通过使用以下优化代码,我能够将其降至8-10ms:

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <numeric>
#include <vector>

int main() {
    int x = 0;
    int n = 0;
    std::cin >> x >> n;
    std::vector<decltype(x)> vect(n);
    bool vect_contains_x = false;
    for (auto& elem : vect) {
        std::cin >> elem;
        if (elem == x) {
            vect_contains_x = true;
        }
    }
    int num = 0;
    if (!vect_contains_x) {
        num = x;
    }
    else {
        std::sort(vect.begin(), vect.end());
        auto isPresent = [=](auto num) {
            for (const auto& elem : vect) {
                if (num == elem) {
                    return true;
                }
            }
            return false;
        };
        while (1) {
            static int i = 1;
            if (!isPresent(x - i)) {
                num = x - i;
                break;
            }
            else if (!isPresent(x + i)) {
                num = x + i;
                break;
            }
            else {
                i += 1;
            }
        }
    }
    std::cout << num << "\n";
    return 0;
}

但是,这两种代码的问题(因为它们都使用相同的方法)在于,如果给定列表中存在大量连续的整数流,则如下所示:

1,2,3,4,5,6,7,8,9,10,。。。,1501

给出的X是

751

代码将需要对for loop进行750次迭代,这是非常多的。 我们能不能用更好的算法找到最接近的整数?

编辑:

通过使用binary_search(谢谢@Sebastian)将其降至6ms,但算法仍然保持不变。。。


共2个答案

匿名用户

根据你的链接,整数的总数最多是100。 因此,100位足以保存标志,这些数字出现在序列中。 它们可以保存在处理器寄存器中。

下面的代码只显示了存储空间,后面您必须选择合适的位扫描操作:

#include <cstdlib>
#include <iostream>
#include <numeric>
#include <limits>
#include <bitset>

using namespace std;

int main() {
    bitset<100> flags;
    int x = 0;
    int n = 0;
    int min = std::numeric_limits<int>::max();
    int num = 0;
    std::cin >> x >> n;
    for (int i = 0; i < n; i++) {
        int elem;
        std::cin >> elem;
        flags.set(elem);
    }
    // then you can shift the result by x bits and do bit scan operations
    // there are built-ins depending on the compiler and processor architecture or the portable De Bruijn with multiplications
}
// alternatively (to the shift) you can use two bitsets, and for one set all the elements (elem - x) or for the other (x - elem)

匿名用户

这是我的O(N)的代码,我的代码需要6ms来求解。

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


#define FastIO ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

const int inf = 1e9;

int is_find[200];
int main()
{
FastIO
int value, x, n;

cin >> x >> n;
for(int i = 0; i < n; i++) 
{
    cin >> value;
    is_find[ value ] = 1;
}

int ans = -1, mn = inf;
for(int i = 0; i <= 101; i++)
{
    if(is_find[i] == 0){

        if(mn > abs(i - x)){
            mn = abs(i - x);
            ans = i;
        }
    }
}

cout << ans << endl;


return 0;
}
///Before submit=>
///    *check for integer overflow,array bounds
///    *check for n=1