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

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

本文关键字:数字 列表 不存在 整数 何优化 优化 代码 最接近 返回      更新时间:2023-10-16

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


给定一个整数 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


代码将需要 750 次迭代for loop,这是很多。我们可以使用更好的算法来找到最接近的整数吗?


编辑

通过使用binary_search将其归结为6ms(谢谢@Sebastian(,但算法仍然保持不变......

你可以看到这个"作弊"算法。这是作弊,因为_Find_next方法仅在GCC编译器中。此外,在printfscanf的帮助下,我加快了输入和输出,因此程序运行得更快。我多次发送它执行并收到 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;
}

我并不是说这个"算法"比你的更好。但是,据我了解,您要求其他一些解决方案,这是可能的一种。

根据您的链接,整数总数最多为 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)