简体   繁体   English

如何优化代码以返回最接近给定 integer 的数字,但不存在于给定列表中?

[英]How do I optimise the code to return the number closest to a given integer, not present in the given list?

I solved this problem statement (Yeah Yeah, I know, I am putting the problem statement below).我解决了这个问题陈述(是的,我知道,我将问题陈述放在下面)。


Given are an integer X and an integer sequence of length N: p1, …, pN.给定长度为 N 的 integer X 和 integer 序列:p1,...,pN。 Among the integers not contained in the sequence p1, …, pN (not necessarily positive), find the integer nearest to X, ie the integer whose absolute difference with X is the minimum.在序列p1,...,pN(不一定是正数)中不包含的整数中,找到离X最近的integer,即与X的绝对差值最小的integer。 If there are multiple such integers, report the smallest such integer如果有多个这样的整数,报告最小的这样 integer


This is the code I used:这是我使用的代码:

#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;
}

This code renders the result in 13-18ms .此代码在13-18ms呈现结果。


I was able to get it down to 8-10ms by using the following optimised code:通过使用以下优化代码,我能够将其降低到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;
}

However, the problem with both the codes (as they both use the same approach) is that, If there is a large continuous stream of integers in the given list, something like:但是,这两个代码的问题(因为它们都使用相同的方法)是,如果给定列表中有一个大的连续 stream 整数,例如:

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

and the X given is给定的 X 是

751 751


The code will need 750 iterations of the for loop , which is a lot.该代码将需要 750 次for loop迭代,这很多。 Can we use a better algorithm to find the closest integer?我们可以使用更好的算法来找到最接近的 integer 吗?


EDIT :编辑

Got it down to 6ms by using binary_search (Thanks @Sebastian), but still, the algorithm remains the same...使用6ms将其缩短到binary_search (感谢@Sebastian),但算法仍然保持不变......

You can see this "cheating" algorithm.你可以看到这个“作弊”算法。 It's cheating because the _Find_next method is only in the GCC compiler.这是作弊,因为_Find_next方法仅在GCC编译器中。 Also, with the help of printf and scanf , I accelerated input and output, due to which the program runs faster.此外,在printfscanf的帮助下,我加速了输入和 output,因此程序运行得更快。 I sent it for execution several times and received 4, 6 and 8 ms (6 ms most often):我多次发送它执行并收到 4、6 和 8 毫秒(最常见的是 6 毫秒):

#include <bitset>
#include <algorithm>

using namespace std;

int main()
{
    const int MAX_VALUES = 101;
    bitset<MAX_VALUES> bits;
    bitset<MAX_VALUES> reversed;
    bits.flip();
    reversed.flip();
    int x, n, t;
    scanf("%d %d", &x, &n);
    if (n == 0) {
        printf("%d", x);
        exit(0);
    }
    for (int i = 0; i < n; i++) {
        scanf("%d", &t);
        bits.reset(t);
        reversed.reset(MAX_VALUES - 1 - t);
    }
    if (bits[x]) {
        printf("%d", x);
        exit(0);
    }
    int rV = bits._Find_next(x);
    int lV = MAX_VALUES - 1 - reversed._Find_next(MAX_VALUES - 1 - x);
    int d1 = abs(rV - x);
    int d2 = abs(lV - x);
    if (d1 < d2) {
        printf("%d", rV);
    } else if (d2 < d1) {
        printf("%d", lV);
    } else {
        printf("%d", min(rV, lV));
    }
    return 0;
}

I am not saying that this "algorithm" is better than yours.我并不是说这个“算法”比你的更好。 But, as I understand it, you asked for some other solutions, this is one of the possible.但是,据我了解,您要求其他一些解决方案,这是可能的方法之一。

According to your link, the total number of integers is at most 100. So 100 bits are enough to hold the flags, which numbers appear in the sequence.根据您的链接,整数的总数最多为 100。因此 100 位足以容纳标志,这些数字出现在序列中。 Those can be held in the processor registers.这些可以保存在处理器寄存器中。

The following code shows only the storage, afterwords you would have to chose suitable bit scan operations:以下代码仅显示了存储,您必须选择合适的位扫描操作:

#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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM