有序数组的二分查找实现

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

-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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值