-
Notifications
You must be signed in to change notification settings - Fork 21
/
floor_ceil_BinarySearch.cpp
executable file
·144 lines (118 loc) · 4.11 KB
/
floor_ceil_BinarySearch.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//
// Created by light on 19-9-2.
//
#include <iostream>
#include <cassert>
#include <ctime>
#include <vector>
using namespace std;
// 二分查找法, 在有序数组arr中, 查找target
// 如果找到target, 返回第一个target相应的索引index
// 如果没有找到target, 返回比target小的最大值相应的索引, 如果这个最大值有多个, 返回最大索引
// 如果这个target比整个数组的最小元素值还要小, 则不存在这个target的floor值, 返回-1
/**
* 当存在大量重复的元素时,floor找的是第一个。
* 当不存在指定的元素时,floor是比其小最大的一个。
* @tparam T
* @param arr
* @param n
* @param target
* @return
*/
template<typename T>
int floor(T arr[], int n, T target){
assert( n >= 0 );
// 寻找比target小的最大索引
int l = -1, r = n-1;
while( l < r ){
// 使用向上取整避免死循环
int mid = l + (r-l+1)/2;
if( arr[mid] >= target )
r = mid - 1;
else
l = mid;
}
assert( l == r );
// 如果该索引+1就是target本身, 该索引+1即为返回值
if( l + 1 < n && arr[l+1] == target )
return l + 1;
// 否则, 该索引即为返回值
return l;
}
// 二分查找法, 在有序数组arr中, 查找target
// 如果找到target, 返回最后一个target相应的索引index
// 如果没有找到target, 返回比target大的最小值相应的索引, 如果这个最小值有多个, 返回最小的索引
// 如果这个target比整个数组的最大元素值还要大, 则不存在这个target的ceil值, 返回整个数组元素个数n
/**
* 当存在大量重复的元素时,ceil找的是第一个。
* 当不存在指定的元素时,ceil是比其大最小的一个。
* @tparam T
* @param arr
* @param n
* @param target
* @return
*/
template<typename T>
int ceil(T arr[], int n, T target){
assert( n >= 0 );
// 寻找比target大的最小索引值
int l = 0, r = n;
while( l < r ){
// 使用普通的向下取整即可避免死循环
int mid = l + (r-l)/2;
if( arr[mid] <= target )
l = mid + 1;
else // arr[mid] > target
r = mid;
}
assert( l == r );
// 如果该索引-1就是target本身, 该索引+1即为返回值
if( r - 1 >= 0 && arr[r-1] == target )
return r-1;
// 否则, 该索引即为返回值
return r;
}
class Solution {
public:
int ceil(vector<int>& nums, int n,int target) {
if (nums.size() == 0) return -1;
int left = 0, right = n-1;
while (left <= right) {
int mid =left+ (right-left) / 2;
if (nums[mid] == target) {
left = mid + 1; // 注意
} else if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid-1;
}
}
if(right<0) return 0; // 或者写if(left==0) return -1; 如果right<0,那么此时nums中所有元素均大于target
return nums[right] == target ? right : right+1;
}
};
// 测试我们用二分查找法实现的floor和ceil两个函数
// 请仔细观察在我们的测试用例中,有若干的重复元素,对于这些重复元素,floor和ceil计算结果的区别:)
int main(){
int a[] = {1, 1, 1, 2, 2, 2, 2, 2, 4, 4, 5, 5, 5, 6, 6, 6};
int n = sizeof(a)/sizeof(int);
cout<<n<<endl;
int floorIndex = ceil(a, n, 0);
cout<<floorIndex<<endl;
for( int i = 0 ; i <= 10 ; i ++ ){
int ceilIndex = ceil(a, sizeof(a)/sizeof(int), i);
cout<<"the ceil index of "<<i<<" is "<<ceilIndex<<".";
if( ceilIndex >= 0 && ceilIndex < n )
cout<<"The value is "<<a[ceilIndex]<<".";
cout<<endl;
}
vector<int> nums= {1, 1, 1, 2, 2, 2, 2, 2, 4, 4, 5, 5, 5, 6, 6, 6};
for( int i = 0 ; i <= 10 ; i ++ ){
int ceilIndex =Solution().ceil(nums,n,i);
cout<<"the ceil index of "<<i<<" is "<<ceilIndex<<".";
if( ceilIndex >= 0 && ceilIndex < n )
cout<<"The value is "<<nums[ceilIndex]<<".";
cout<<endl;
}
return 0;
}