0、Leetcode704バイナリ検索
n要素の順序付き(昇順)整数配列numsとターゲット値targetが与えられた場合、numsでターゲットを検索する関数を記述し、ターゲット値が存在する場合は添え字を返し、そうでない場合は-1を返します。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size()-1;// 在【left,right】范围里寻找target
while(left <= right){
// 当left == right时,区间【left,right】仍然有效,该继续查找,所以是left <= right
int mid = left + (right-left)/2;
if(nums[mid] == target){
return mid;
}
if(target > nums[mid]){
left = mid + 1;//target在【mid+1, right】中
}else{
right = mid - 1;//target在【left, mid+1】中
}
}
return -1; // 没有找到
}
};
変数の意味を明確にし、ループ不変条件を維持し、少量のデータでデバッグし、大量のデータでテストします。
上記のコードは[左、右]でターゲットを検索し、次のコードは[左、右]でターゲットを検索します。
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size();// 在【left,right)范围里寻找target
while(left < right){
// 当left == right时,区间【left,right)无效,不该继续查找,所以是left < right
int mid = left + (right-left)/2;
if(nums[mid] == target){
return mid;
}
if(target > nums[mid]){
left = mid + 1;//target在【mid+1, right)中
}else{
right = mid;//target在【left, mid)中
}
}
return -1; // 没有找到
}
};
1.バイナリ検索の古典的な実装
/*************************最基本的二分查找*********************************/
int BinarySearchUp(int * nums,int numslen,int key){
//针对升序数组,非递归实现
int high, low, mid;
high = numslen - 1;
low = 0;
while (low <= high){
mid = high - (high - low) / 2;//更新mid的位置
if (key == nums[mid]){
//找到了
return mid;
}
else if (key < nums[mid]){
//key在左半边
high = mid - 1;
}
else{
//key在右半边
low = mid + 1;
}
}
return -1;
}
int BinarySearchDown(int * nums, int numslen, int key){
//针对降序数组,非递归实现
int high, low, mid;
high = numslen - 1;
low = 0;
while (low <= high){
mid = high - (high - low) / 2;//更新mid的位置
if (key == nums[mid]){
//找到了
return mid;
}
else if (key < nums[mid]){
//key在右半边
low = mid + 1;
}
else{
//key在左半边
high = mid - 1;
}
}
return -1;
}
int BinarySearchUpRecursive(int * nums, int low, int high, int key){
//针对升序数组,采用递归实现
//边界条件判断
if (low > high){
return -1;
}
int mid = low + (high - low) / 2;//计算mid的位置
if (key == nums[mid]){
//找到了
return mid;
}
else if (key > nums[mid]){
//key在右半边
return BinarySearchUpRecursive(nums, mid + 1, high, key);
}
else{
//key在左半边
return BinarySearchUpRecursive(nums, low, mid - 1, key);
}
}
2.配列に繰り返し要素が含まれている場合、繰り返し要素の左右の境界を見つけます
2-1。目標値領域の左側の境界を見つける=目標値に等しい最初の要素の位置を見つける=目標値以上の最初の要素の位置を見つける
/*************************查找目标值区域的左边界*******************************************/
/*************************查找与目标值相等的第一个元素位置*********************************/
/*************************查找第一个不小于目标值的元素位置*********************************/
int BinarySearchLowerBound(int * nums, int numslen, int key){
int low = 0, high = numslen - 1, mid;
while (low <= high){
mid = low + (high - low) / 2;
if (key <= nums[mid]){
//不在右半边
high = mid - 1;
}
else{
//在右半边
low = mid + 1;
}
}
if (nums[low] == key){
//low < numslen &&
return low;
}
else{
return -1;
}
}
2-2。目標値領域の右境界を見つける=目標値に等しい最後の要素位置を見つける=目標値以下の最初の要素位置を見つける
/*************************查找目标值区域的右边界*******************************************/
/*************************查找与目标值相等的最后一个元素位置*********************************/
/*************************查找第一个不大于目标值的元素位置*********************************/
int BinarySearchUpperBound(int * nums,int numslen, int key){
int low = 0, high = numslen - 1, mid;
while (low <= high){
mid = low + (high - low) / 2;
if (key >= nums[mid]){
//不在左侧
low = mid + 1;
}
else{
//在左侧
high = mid - 1;
}
}
if (key == nums[high]){
//high >= 0 &&
return high;
}
else{
return -1;
}
}
2-3。目標値よりも大きい最初の数値を見つける=目標値よりも大きいが目標値に最も近い数値を見つける
/*************************查找第一个大于目标值的数*******************************************/
/*************************查找比目标值大但是最接近目标值的数*********************************/
/*
我们已经找到了最后一个不大于目标值的数,那么再往后进一位,
返回high + 1,就是第一个大于目标值的数。*/
int BinarySearchBiggerOne(int * nums,int numslen,int key){
int low = 0, high = numslen - 1, mid;
while (low <= high){
mid = low + (high - low) / 2;
if (key >= nums[mid]){
//不在左边
low = mid + 1;
}
else{
high = mid - 1;
}
}
if (high+1 < numslen && key == nums[high]){
return high + 1;
}
else{
return -1;
}
}
2-4。目標値よりも小さい最後の数値を見つける=目標値よりも小さいが目標値に最も近い数値を見つける
/*************************查找最后一个小于目标值的数*******************************************/
/*************************查找比目标值小但是最接近目标值的数*********************************/
int BinarySearchLessOne(int * nums, int numslen, int key){
int low = 0, high = numslen - 1, mid;
while (low <= high){
mid = low + (high - low) / 2;
if (key <= nums[mid]){
//不在右边
high = mid - 1;
}
else{
//在右边
low = mid + 1;
}
}
if (low - 1 >= 0 && key == nums[low]){
return low - 1;
}
else{
return -1;
}
}
3.回転アレイの問題
3-1。回転した配列の最小要素添え字を見つけます(繰り返し番号がないと仮定します)
/*************************查找旋转数组的最小值元素下标(假设不存在重复数字)*********************************/
int BinarySearchRotateMinUnique(int * nums, int numslen){
int low = 0, high = numslen - 1, mid;
while (low < high){
mid = low + (high - low) / 2;
if (nums[mid] > nums[high]){
//说明最小值在右半边
low = mid + 1;
}
else{
//说明最小值不在右半边
high = mid;
}
}
return high;//此时low=high,写return high;一样的
}
3-2、回転した配列の最小要素添え字を見つけます(重複する番号があると仮定します)
/*************************查找旋转数组的最小值元素下标(假设存在重复数字)*********************************/
int BinarySearchRotateMinRepeated(int * nums, int numslen){
int low = 0, high = numslen - 1, mid;
while (low < high){
mid = low + (high - low) / 2;
if (nums[mid] > nums[high]){
//最小值在右半边
low = mid + 1;
}
else if (nums[mid] < nums[high]){
//最小值不在右半边
high = mid;
}
else{
//最小值可能为当前值,也可能在左半边,也可能在右半边
high--;//小步前进
}
}
return low;
}
3-3。回転するソートされた配列を検索します(重複する番号がないと仮定します)
/*************************在旋转排序数组中搜索(假设不存在重复数字)*********************************/
int BinarySearchKeyInRotateUnique(int * nums, int numslen, int key){
int low = 0, high = numslen - 1, mid;
while (low <= high){
mid = low + (high - low) / 2;
if (key == nums[mid]){
return mid;
}
else if (nums[low] <= nums[mid]){
//左半边是有序的
if (key >= nums[low] && key < nums[mid]){
//key在左半边
high = mid - 1;
}
else{
//key在右半边
low = mid + 1;
}
}
else if (nums[mid] <= nums[high]){
//右半边是有序的
if (key>nums[mid] && key <= nums[high]){
//key在右半边
low = mid + 1;
}
else{
//key在左半边
high = mid - 1;
}
}
}
return -1;
}
3-4。回転するソートされた配列を検索します(重複する番号があると想定)
/*************************在旋转排序数组中搜索(假设存在重复数字)*********************************/
bool BinarySearchKeyInRotateRepeat(int * nums, int numslen, int key){
int low = 0, high = numslen - 1, mid;
while (low <= high){
mid = low + (high - low) / 2;
if (key == nums[mid]){
return true;
}
else if (nums[low] < nums[mid]){
//左半边有序
if (key >= nums[low] && key < nums[mid]){
//key在左半边
high = mid;
}
else{
//key在右半边
low = mid + 1;
}
}
else if (nums[mid] < nums[high]){
//右半边有序
if (key > nums[mid] && key <= nums[high]){
//key在右半边
low = mid + 1;
}
else{
//key在左半边
high = mid;
}
}
else {
high--;
}
}
return false;
}
4.上記の機能をテストします
#include<iostream>
using namespace std;
假装这里有上述的所有函数
int main(){
int data[] = {
6, 5, 4, 3, 2, 1 };
int data2[] = {
1, 2, 3, 4, 5, 6 };
int data3[] = {
1, 3, 7, 7, 7, 14, 14, 14 };
int data4[] = {
4, 5, 6, 7, 8, 1, 2, 3 };
int data5[] = {
5, 5, 5, 6, 7,7,7, 8,8, 2, 2, 2, 3 };
这里调用函数即可
bool num = BinarySearchKeyInRotateRepeat(data5, 13, 2);//此种情况显示的是有或无
cout << "Index of the number is " << num <<"."<<endl;
system("pause");
return 0;
}