01、二分查找
(1)二分查找
对于二分查找,关键就是要主要的核心,就是在一个有序的数组中,不断的将查找的元素对半缩小,知道找到了那个元素,如果没有找到就返回 -1 ,标价这个元素是不存的在
主要的核心算法如下:
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0 ,right = nums.size() - 1;
while (left <= right){
int mid = left + (right - left) / 2;
if (target ==nums[mid]){
return mid;
}else if(target > nums[mid]){
left = mid + 1;
}else if (target <nums[mid] ){
right = mid - 1;
}
}
return -1;
}
};
但是上面的代码适合的情况只能是在两边的取值可以同时取的时候,如果是[ , )这种情况就要换一种了,其实也就是将while循环的条件改为了 left < right ;其他的都没变罢了
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0 ,right = nums.size() - 1;
while (left < right){
int mid = left + (right - left) / 2;
if (target ==nums[mid]){
return mid;
}else if(target > nums[mid]){
left = mid + 1;
}else if (target <nums[mid] ){
right = mid - 1;
}
}
return -1;
}
};
搞笑的是,在我第一次写的时候我居然没有比较数组中的值,反而比较的是下标,后面提交的时候才反应过来;
比较好的是,在函数中用的是 vector
下面是测试的结果:

(2) 二分查找的基础上返回插入的元素
题目如下:
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例 1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例 2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例 3:
输入:nums = [], target = 0
输出:[-1,-1]
在我第一次写的时候我在判断返回插入元素的位置的时候,想得太复杂了,在每个判断条件中我都嵌套了条件
# 这样做判断太复杂了
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
// 有两个步骤,第一是先查找,找到了就返会
int left = 0 , right = nums.size() - 1;
while (left <= right){
int mid = left + (right - left) /2;
if (target == nums[mid]){
return mid;
}else if (target < nums[mid]){
right = mid -1;
if (target < nums[right] && target > nums[right - 1]){
return right;
}
}else{
left = mid + 1;
if (target > nums[nums.size() - 1]){
return nums.size();
}else if ( target > nums[left] && target < nums[left + 1]){
return left + 1;
}
}
}
return nums.size();
// 第二步是如果没有找到就要返回需要插入的位置
很显然当时是不太了解二分法的,修改后的代码是:
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
// 有两个步骤,第一是先查找,找到了就返会
int left = 0 , right = nums.size()- 1;
while (left <= right){
int mid = left + (right - left) /2;
if (target == nums[mid]){
return mid;
}else if (target < nums[mid]){
right = mid -1;
}else{
left = mid + 1;
}
}
return left;
// 第二步是如果没有找到就要返回需要插入的位置
}
};
我当时思考了一下,当上面查找的时候如果都没有找到,那么就肯定在变量left 或者是right的附近,具体分析下来就是
如果查找的元素是比数组中的元素都要大,那么就是将left不断的右移动 , 而循环条件是left <= right ; 所以可以移动到最右边,
再次遍历的时候left + 1 , 此时刚好结束循环 ,然后直接返回 left ,就直接找到了需要出入的元素,实在是太巧了,比我刚才的想的简洁的太多了;
当我提交之后显然是


浙公网安备 33010602011771号