给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
来源:力扣(LeetCode)
解题代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
int min = 0;
int max = size(nums) - 1 ; //获取数组的长度
while (min <= max){
int mid = (min + max) / 2;
if (nums[mid] < target)
min = mid + 1;
else if (nums[mid] > target)
max = mid - 1;
else
return mid;
}
return -1;
}
};
第一点:
首先复习一下向量的有关知识。
向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。
1.push_back 在数组的最后添加一个数据
2.pop_back 去掉数组的最后一个数据
3.at 得到编号位置的数据
4.begin 得到数组头的指针
5.end 得到数组的最后一个单元+1的指针
6.front 得到数组头的引用
7.back 得到数组的最后一个单元的引用
8.max_size 得到vector最大可以是多大
9.capacity 当前vector分配的大小
10.size 当前使用数据的大小
11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
12.reserve 改变当前vecotr所分配空间的大小
13.erase 删除指针指向的数据项
14.clear 清空当前的vector
15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)
16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)
17.empty 判断vector是否为空
18.swap 与另一个vector交换数据
第二点:
二分查找。这道题目的前提是数组为有序数组,同时题目还强调数组中无重复元素,因为一旦有重复元素,使用二分查找法返回的元素下标可能不是唯一的,这些都是使用二分法的前提条件,当大家看到题目描述满足如上条件的时候,可要想一想是不是可以用二分法了。
二分查找确实很简单,但是容易写错,为啥呢,就是涉及到很多边界条件。
- while (left <= right) 要使用 <= ,left == right是有意义的
- if (nums[mid] > target) max 要赋值为 mid - 1,因为当前这个nums[mid]一定不是target,那么接下来要查找的左区间结束下标位置就是 middle - 1
第三点:
二分查找可以有很多应用,有时候查找条件可以改变。不一定是查找target,可以是target的变式或者其他条件的变式。
二分查找停止时的特点是要不找到元素,要不会停止在最接近target的两个位置处,而且此时right在 左,left在右。
例一:69. x的平方根
题目描述:给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5
解答:
class Solution {
public:
//使用二分查找,找出第一个平方大于x的数,其前一个数即为x平方根的整数部分
int mySqrt(int x) {
int left=0,right=x,mid;
while(left <= right){
mid = left + (right-left)/2;//防止溢出
if((long long) mid * mid > x )
right=mid-1;
else
left=mid+1;
}
//如果没找到二分查找最终一定会停在两个最接近target的地方,right在左,left在右
return left-1;
}
};
例二:367.有效的完全平方数
题目描述:给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
进阶:不要 使用任何内置的库函数,如 sqrt 。
解答:
class Solution {
public:
bool isPerfectSquare(int num) {
int left = 0, right = num,mid;
while (left <= right){
mid = left + ((right - left)/2);
if ((long long)mid * mid > num )
right = mid - 1;
else
left = mid + 1;
}
if ((long long)right * right == num)
return true;
else
return false;
}
};