找到最后一个不大于target的元素以及找到第一个不小于targ
2020-02-24 本文已影响0人
不知名小号
findLastNotBiggerThan,找到最后一个不大于target的元素,返回下标。
假设l, r是可能产生结果的区间。
l和r取中间mid
如果v[mid] <= target,则说明mid左边的数都是小于等于target的,而且mid又是这些数里最右边的,所以,相比于mid左边的数,mid更有可能是答案,故排除mid左边的数,令l = mid。
否则,v[mid] > target,我们要找的是不大于,所以mid不可能是解,并且mid右边的数都是大于v[mid]的,故将mid和mid右边的数都排除,即r = mid - 1
findFirstNotSmallThan,找到第一个不小于target的元素,返回下标
如果v[mid] >= target,那它右边的数都大于target,而且mid是这些数里最靠左的,所以排除了mid右边的元素,r = mid。
否则,v[mid] < target,那它左边的元素都是小于target的,mid本身不符合答案,mid左边的元素也不符合,所以l = mid + 1。
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define ms(s) memset(s, 0, sizeof(s))
const int inf = 0x3f3f3f3f;
const int maxn = 1e5 + 7;
#define LOCAL
int findLastNotBiggerThan(std::vector<int> v, int target){
int l = 0, r = v.size() - 1;
while (l < r){
int mid = (l + r + 1) / 2;
if (v[mid] <= target){
l = mid;
}
else{
r = mid - 1;
}
}
return l;
}
int findFirstNotSmallThan(std::vector<int> v, int target){
int l = 0, r = v.size() - 1;
while (l < r){
int mid = (l + r) / 2;
if (v[mid] >= target){
r = mid;
}
else{
l = mid + 1;
}
}
return l;
}
int main(int argc, char * argv[])
{
// std::vector<int> v(1, 1, 2, 3, 5, 8);
int a[] = {1, 1, 2, 3, 3, 4, 4, 4, 5, 6, 8, 10};
vector<int> v(a, a + 12);
for (int i = 0; i < v.size(); i++){
cout << i << ": " << v[i] << " | ";
}
cout << endl;
while (1){
int t;
cin >> t;
cout << "findFirstNotSmallThan(v, t)" << endl;
cout << findFirstNotSmallThan(v, t) << endl;
cout << "findLasttNotBiggerThan(v, t)" << endl;
cout << findLastNotBiggerThan(v, t) << endl;
}
return 0;
}