1. 有序数组,查找确定值
实现一
#include<iostream>
#include<vector>
using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = array.size();
while (left < right) {
int mid = (left + right) / 2;
if (array[mid] == target) return mid;
else if (array[mid] < target) left = mid + 1;
else right = mid;
}
return -1;
}
int main(int argc, char const *argv[]) {
vector<int> input{1,2,3,4,5,6};
cout << binarySearch(input, 3) << endl;
cout << binarySearch(input, 100) << endl;
cout << binarySearch(input, -100) << endl;
return 0;
}
输出
2
-1
-1
总结
- right初始化:right = arra.size()
- 循环条件:left < right
- 更新right值:right = mid
实现二
#include<iostream>
#include<vector>
using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = array.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid] == target) return mid;
else if (array[mid] < target) left = mid + 1;
else right = mid - 1;
}
return -1;
}
int main(int argc, char const *argv[]) {
vector<int> input{1,2,3,4,5,6};
cout << binarySearch(input, 3) << endl;
cout << binarySearch(input, 100) << endl;
cout << binarySearch(input, -100) << endl;
return 0;
}
输出
2
-1
-1
总结
- right初始化:right = arra.size() - 1
- 循环条件:left <= right
- 更新right值:right = mid - 1
2. 有序数组,查找不确定值
2.1 查找第一个不小于目标值的数
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = array.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] < target) left = mid + 1;
else right = mid;
}
return right;
}
int main(int argc, char const *argv[]) {
vector<int> input{2, 4, 5, 6, 9};
cout << binarySearch(input, 3) << endl;
cout << binarySearch(input, 100) << endl;
cout << binarySearch(input, -100) << endl;
return 0;
}
输出
1
5 // 当目标值大于数组中所有元素时,只能输出最后一个元素索引
0
问题
当目标值大于数组中所有元素时,只能输出最后一个元素索引
总结
- right初始化:right = arra.size()
- 循环条件:left < right
- 更新right值:right = mid
- 大小判断:array[mid] < target
- 不需要判断是否相等:array[mid] == target
2.2 查找最后一个小于目标值的数
从查找第一个不小于目标值的数:
return right;
查找最后一个小于目标值的数:
return right - 1;
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = array.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] < target) left = mid + 1;
else right = mid;
}
return right - 1;
}
int main(int argc, char const *argv[]) {
vector<int> input{2, 4, 5, 6, 9};
cout << binarySearch(input, 3) << endl;
cout << binarySearch(input, 100) << endl;
cout << binarySearch(input, -100) << endl;
return 0;
}
输出
0
4
-1 // 当目标值小于数组中所有元素时,只能输出-1
问题
当目标值小于数组中所有元素时,只能输出-1
总结
- right初始化:right = arra.size()
- 循环条件:left < right
- 更新right值:right = mid
- 大小判断:array[mid] < target
- 不需要判断是否相等:array[mid] == target
2.3 查找第一个大于目标值的数
查找第一个不小于目标值的数
if (nums[mid] < target) left = mid + 1;
查找第一个大于目标值的数
if (nums[mid] <= target) left = mid + 1;
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = array.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] <= target) left = mid + 1;
else right = mid;
}
return right;
}
int main(int argc, char const *argv[]) {
vector<int> input{2, 4, 5, 6, 9};
cout << binarySearch(input, 3) << endl;
cout << binarySearch(input, 100) << endl;
cout << binarySearch(input, -100) << endl;
return 0;
}
输出
1
5 // 目标值大于数组中的所有元素时,结果输出最后一个元素索引
0
问题
目标值大于数组中的所有元素时,结果输出最后一个元素索引
2.4 查找第一个大于目标值的数
查找第一个大于目标值的数
return right;
查找最后一个不大于目标值的数
return right - 1;
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = array.size();
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] <= target) left = mid + 1;
else right = mid;
}
return right - 1;
}
int main(int argc, char const *argv[]) {
vector<int> input{2, 4, 5, 6, 9};
cout << binarySearch(input, 3) << endl;
cout << binarySearch(input, 100) << endl;
cout << binarySearch(input, -100) << endl;
return 0;
}
输出
0
4
-1 //目标值小于所有元素时,只能返回-1
问题
目标值大于数组中的所有元素时,结果输出最后一个元素索引
3 有序数组旋转
3.1 情形一:无固定target 值
3.1.1 实现一
源码
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array) {
int left = 0, right = (int)array.size() - 1;
while (left < right) {
int mid = left + (right - left) / 2;
if (array[mid] > array[right]) left = mid + 1;
else right = mid;
}
return nums[right];
}
int main(int argc, char const *argv[]) {
vector<int> input{4,5,6,7,0, 1,2};
cout << "no repeat element:" << binarySearch(input) << endl;vector<int> input2{6,6,6,6,6,6,0,1,1,1,6,6};
cout << "has repeat element:" << binarySearch(input2) << endl;
return 0;
}
输出
no repeat element:0
has repeat element:6
问题
- 无法处理数组中含有重复值的情况
- 测试用例还有点要求,比如{6,6,0,1,1,1,6,6}就测试不出bug来
3.1.2 实现二
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array) {
int left = 0, right = (int)array.size() - 1;
while (left < right) {
int mid = (left + right) / 2;
if (array[mid] > array[right]) {
left = mid + 1;
} else if (array[mid] < array[right]) {
right = mid;
} else {
--right;
}
}
return nums[right];
}int main(int argc, char const *argv[]) {
vector<int> input{4,5,6,7,0, 1,2};
cout << "no repeat element:" << binarySearch(input) << endl;vector<int> input2{6,6,6,6,6,6,0,1,1,1,6,6};
cout << "has repeat element:" << binarySearch(input2) << endl;
return 0;
}
输出
no repeat element:0
has repeat element:0
此时,数组中含有重复元素也可以找出最小值
3.1.3 总结
- right初始化:array.size() - 1
- 循环条件:left < right
- 数组有重复元素时,需要处理array[mid] = array[right]:--right
3.2 情形二:有固定target值
实现一
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = (int)array.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid] == target) return mid;
if (array[mid] < array[right]) {
if (array[mid] < target && target <= array[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
} else {
if (target < array[mid] && target >= array[left]) {
right = mid - 1;
} else {
left = mid + 1;
}
}
}
return -1;
}
int main(int argc, char const *argv[]) {
vector<int> input{4,5,6,7,0,1,2};
cout << "no repeat element:" << binarySearch(input, 0) << endl;
vector<int> input2{3,1,1};
cout << "has repeat element:" << binarySearch(input2, 3) << endl;
return 0;
}
输出
no repeat element:4
has repeat element:-1
问题
当有重复元素时,可能会出问题
实现二
#include<iostream>
#include<vector>using namespace std;
int binarySearch(vector<int>& array, int target) {
int left = 0, right = (int)array.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (array[mid] == target) return mid;
if (array[mid] < array[right]) {
if (array[mid] < target && target <= array[right]) {
left = mid + 1;
} else {
right = mid - 1;
}
} else if (array[mid] > array[right]){
if (target < array[mid] && target >= array[left]) {
right = mid - 1;
} else {
left = mid + 1;
}
} else {
--right;
}
}
return -1;
}
int main(int argc, char const *argv[]) {
vector<int> input{4,5,6,7,0,1,2};
cout << "no repeat element:" << binarySearch(input, 0) << endl;
vector<int> input2{3,1,1};
cout << "has repeat element:" << binarySearch(input2, 3) << endl;
return 0;
}
输出
no repeat element:4
has repeat element:0
总结
- right初始化:array.size() - 1
- 循环条件:left < right
- 数组有重复元素时,需要处理array[mid] = array[right]:--right