简体   繁体   English

如何找到最接近给定数字的数字

[英]How to find the closest number to a given number

I have a vector:我有一个向量:

std::vector<int> vec = { 10 , 115 ,15,  35 , 55 , 75 };

I need to find the two numbers closest to a given number.我需要找到最接近给定数字的两个数字。 The first number would be less than the given number and hte second would be greater than the given number.第一个数字将小于给定数字,第二个数字将大于给定数字。

For example if the given number is 40 the two numbers would be 35 and 55 .例如,如果给定的数字是40那么这两个数字将是3555

This is currently how I'm doing it:这就是我目前的做法:

For the smaller number:对于较小的数字:

  1. first I search all the numbers smaller than the given number.首先我搜索所有小于给定数字的数字。
  2. Then I search for the greatest of them all.然后我寻找他们中最伟大的。

The same for the greater number.对于更大的数字也是如此。

I wanted to know if we can do it more efficently?我想知道我们是否可以更有效地做到这一点?

I wanted to know if we can do it more efficently ?我想知道我们是否可以更有效地做到这一点?

If the vector is not sorted, sorting it would be a waste wrt asymptotic complexity (for time), and you might just want to use two sequential for loops to find the less than and greater than values, respectively.如果未对向量进行排序,则对其进行排序将浪费渐近复杂度(时间),并且您可能只想使用两个连续的for循环来分别查找小于和大于值。 Eg:例如:

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

// Returns a pair of closest less than (first) and greater
// than (second) numbers in 'vec' to that of 'number'.
// If a less than or greater than number can't be found,
// the value of 'number' is returned for that slot.
//
// Time complexity:  O(N)
// Space complexity: O(1)
auto closestNumbers(const std::vector<int> &vec, int number) {
  std::pair closest_numbers{number, number};

  // Find closest below.
  for (auto e : vec) {
    if (e < number &&
        (e > closest_numbers.first || closest_numbers.first == number)) {
      closest_numbers.first = e;
    }
  }
  // Find closest above.
  for (auto e : vec) {
    if (e > number &&
        (e < closest_numbers.second || closest_numbers.second == number)) {
      closest_numbers.second = e;
    }
  }

  return closest_numbers;
}

int main() {
  const auto v = {10, 115, 15, 35, 55, 75};

  auto closest_numbers{closestNumbers(v, 40)};
  std::cout << closest_numbers.first << " " << closest_numbers.second
            << "\n"; // 35 55

  closest_numbers = {closestNumbers(v, 130)};
  std::cout << closest_numbers.first << " " << closest_numbers.second
            << "\n"; // 115 130

  closest_numbers = {closestNumbers(v, 1)};
  std::cout << closest_numbers.first << " " << closest_numbers.second; // 1 10
}

I would sort the array using something like std::sort .我会使用std::sort东西对数组进行std::sort And that's it, the next is the closest higher the previous is the closest lower.就是这样,下一个是最近的较高的,前一个是最近的较低的。

eg:例如:

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

int main()
{
    int value = 1000;
    std::vector<int> vec = {10, 115, 15, 35, 55, 75};

    std::sort(vec.begin(), vec.end()); //sort

    //find the next greatest, in this case, *it would be 55
    auto it = find_if(vec.begin(), vec.end(), [value](int i) { return i > value; });

    //print the next larger if found, if not, print "Not found"
    it != vec.end() ? (std::cout << "Next larger: " << *it) : (std::cout << "Larger not found");
    std::cout << "\n";
    //print the next smaller if found, if not, print "Not found"
    *(it - 1) != value  && it != vec.begin() ? (std::cout << "Next smaller: " << *(it - 1)) : (std::cout << "Smaller not found");

}

What's left is to check if the value matches any element in the array, if so next smaller will be in *(it - 2) (if no repeated numbers are allowed), pending bounds check.剩下的就是检查该值是否与数组中的任何元素匹配,如果匹配,下一个较小的将在*(it - 2) (如果不允许重复数字)中,等待边界检查。

For number = 1 the program outputs:对于number = 1 ,程序输出:

Next larger: 10
Smaller not found

For number = 40 the program outputs:对于number = 40 ,程序输出:

Next larger: 55
Next smaller: 35

For number = 200 the program outputs:对于number = 200 ,程序输出:

Larger not found
Next smaller: 115

You could do your own algorithm by looking for larger/smaller values and saving the upper/lower limit of these values in temporaries along the way, ending up with a O(n) algorithm, wich, I gather, would be the best possible optimization apart from using some complex data structures.您可以通过寻找更大/更小的值并在此过程中临时保存这些值的上限/下限来执行自己的算法,最终得到 O(n) 算法,我认为这将是最好的优化除了使用一些复杂的数据结构。

I would argue that using standard algorithms would be preferable, they are safer and the gains in performance don't justify the hassle, but that's for you to decide.我认为使用标准算法会更可取,它们更安全,性能的提高并不能证明麻烦是合理的,但这由你来决定。


This problem can be solved efficiently in O(log n) by using Binary Search Tree (BST) (the construction is in O(n log n).这个问题可以通过使用二叉搜索树 (BST)在 O(log n) 中有效地解决(构造在 O(n log n) 中)。

In C++, we can use std::set which is implemented by Red–black_tree (kind of self-balancing binary search tree.).在 C++ 中,我们可以使用由Red–black_tree (一种自平衡二叉搜索树)实现的std::set

void test_BST()
{
    std::vector<int> vec = { 10 , 115 ,15,  35 , 55 , 75 };
    int searched_key = 40;
    
    std::set<int> my_BST(vec.begin(),vec.end());

    auto lower_bound = my_BST.lower_bound(searched_key);
    auto upper_bound = my_BST.upper_bound(searched_key);

    cout<<" Value Before = " << *(lower_bound.operator--())<<endl;
    cout<<" Value After = " << *upper_bound<<endl;
}

The result is :结果是:

Value Before = 35
Value After = 55

You asked :你问 :

  1. first I search all the numbers smaller than the given number.首先我搜索所有小于给定数字的数字。
  2. Then I search for the greatest of them all.然后我寻找他们中最伟大的。

I wanted to know if we can do it more efficently?我想知道我们是否可以更有效地做到这一点?

Answer:回答:

Besides using a pre-sorted vector, then yes it can be done more efficiently, just iterate once over the vector and find both at once instead of iterating two times.除了使用预先排序的向量之外,是的,它可以更有效地完成,只需在向量上迭代一次并一次找到两者,而不是迭代两次。 ( here is how to do it with sorting ) 这是如何通过排序来做到这一点

(Note that this answer was posted prior to OP stating the input vector was not sorted) (请注意,此答案是在 OP 之前发布的,说明输入向量未排序)


The the vector is pre-sorted, eg by means of:该向量是预先排序的,例如通过:

std::sort

then然后

std::lower_bound

can be used for the lookup.可用于查找。

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

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