面试题答案
一键面试std::vector
- 提升策略:
- 如果
std::vector
中的元素是有序的,可以使用std::lower_bound
或std::binary_search
。std::lower_bound
返回指向大于或等于目标元素的第一个位置的迭代器,std::binary_search
返回一个布尔值表示元素是否存在。这两个算法的时间复杂度都是$O(\log n)$,而普通find
算法在std::vector
上的时间复杂度是$O(n)$。 - 例如:
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 3, 5, 7, 9}; int target = 5; auto it = std::lower_bound(vec.begin(), vec.end(), target); if (it != vec.end() && *it == target) { std::cout << "Element found at position " << std::distance(vec.begin(), it) << std::endl; } else { std::cout << "Element not found" << std::endl; } return 0; }
- 如果
- 容器结构影响:
std::vector
是连续存储的,支持随机访问。这使得二分查找类的算法(如std::lower_bound
)可以高效地定位元素,因为可以快速通过索引跳跃到中间位置进行比较。
std::list
- 提升策略:
std::list
不支持随机访问,所以不能使用类似二分查找的算法。但是可以通过提前结束查找来优化。例如,如果已知std::list
中元素具有某种顺序特性,可以在找到目标元素或者确定目标元素不存在(例如在升序链表中,当前元素已经大于目标元素)时,及时终止查找。- 例如:
#include <iostream> #include <list> int main() { std::list<int> lst = {1, 3, 5, 7, 9}; int target = 5; for (auto it = lst.begin(); it != lst.end(); ++it) { if (*it == target) { std::cout << "Element found" << std::endl; break; } else if (*it > target) { std::cout << "Element not found" << std::endl; break; } } return 0; }
- 容器结构影响:
std::list
是链式存储,每个元素包含指向前一个和后一个元素的指针。这意味着访问元素只能顺序进行,所以不能使用二分查找这种需要随机访问的算法来提升查找效率。
std::unordered_set
- 提升策略:
std::unordered_set
本身就提供了高效的查找功能,其find
成员函数的平均时间复杂度是$O(1)$。要保持功能不变且尽可能提升效率,只需使用其自身的find
成员函数,而不是使用std::find
算法。- 例如:
#include <iostream> #include <unordered_set> int main() { std::unordered_set<int> uset = {1, 3, 5, 7, 9}; int target = 5; auto it = uset.find(target); if (it != uset.end()) { std::cout << "Element found" << std::endl; } else { std::cout << "Element not found" << std::endl; } return 0; }
- 容器结构影响:
std::unordered_set
基于哈希表实现,通过计算元素的哈希值来快速定位元素所在的桶(bucket),从而实现高效的查找。这种结构使得它在平均情况下查找效率远高于基于线性查找的std::vector
和std::list
,并且不需要元素有序。