班里有 N 个学生,第 i 个学生的分数是
A_i。当且仅当分数 <=A_i的学生数量多于分数比他高的数量时,第 i 个学生会说谎。求出有多少学生会说谎。
今天每日一题刷到了这道题,粗略一看可以用二分查找来找出下标来快速判断其人数的之比。
具体分析和代码如下:
#include <algorithm> #include <bits/stdc++.h> #include <iterator> using namespace std; int solution(std::vector<int> A) { sort(A.begin(), A.end()); int count = 0; for (int i = 0; i < A.size(); i++) { auto it = upper_bound(A.begin(), A.end(), A[i]); int x = distance(A.begin(), it); if (x > (A.size() - x)) count++; } return count; }
算法逻辑
- 排序:首先,我们将所有学生的分数进行排序。排序后,我们可以更容易地计算出每个分数高于和低于某个特定分数的学生数量。
- 查找上界:对于每个学生
i,我们使用upper_bound函数来找到分数大于A[i]的第一个学生的位置。upper_bound返回的是一个迭代器,指向在排序后的数组中第一个大于A[i]的元素。 - 计算数量:通过
distance函数,我们可以计算出A[i]之前有多少学生分数高于它。然后,我们计算出A[i]之后有多少学生分数低于或等于它。 - 判断说谎:如果分数小于或等于
A[i]的学生数量多于分数高于A[i]的学生数量,那么学生i就会说谎。 - 计数:如果满足上述条件,我们将说谎的学生数量加一。
对于这道题来讲核心便是upper_bound这个二分迭代器,便借此来去学习并使用。
lower_bound:前提是有序的情况下,返回指向第一个值不小于 val 的位置,也就是返回第一个大于等于val值的位置。(通过二分查找)
upper_bound:前提是有序的情况下,返回第一个大于val值的位置。(通过二分查找)
通过使用 lower_bound 和 upper_bound,我们可以有效地在排序后的容器中进行查找操作,这对于处理有序数据非常有帮助。这两个函数的时间复杂度为 O(log n),其中 n 是容器的大小,这使得它们在处理大数据集时非常高效。
这两个都可以通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
还有一个函数,
在C++[标准库]中,std::distance()是一个非常有用的函数,可用于计算两个迭代器之间的距离。它提供了一种方便的方法来确定容器中元素的数量,以及在处理[迭代器]范围时进行遍历和计算。它在头文件 **<iterator>**中定义。
比如int distance(A.begin(),it);就是两个迭代器之间的距离