1、704.二分查找
题目:
给定一个 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
提示:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间。
先看题目这个就是使用二分查找,那么二分查找是什么,就是一个数组假如说是有序的,那么只需要求出中间值就可以进行判断,如果这个值大于target的时候,这个数组右边都是比中间这个值小,同理就可以直到左边都是小的,所以就可以确定两个边界,就是left为0,right为nums.size()-1,所以在循环中就可以持续更新,如果小于就是left=mis+1;大于就是right=left-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(nums[mid]<target) left=mid+1; else if(nums[mid]>target) right=mid-1; else return mid; } return -1; } };
2、34.在排序数组中查找元素的第一个和最后一个位置
题目:
给你一个按照非递减顺序排列的整数数组 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]
提示:
0 <= nums.length <= 105
-109 <= nums[i] <= 109
nums
是一个非递减数组-109 <= target <= 109
这个题目就可以看出是要查找一个数的范围,如果找不到就是返回{-1,-1},这里如果直接使用上面一题写的模板时就会很麻烦,所以这里又出现两个变种,分别是查找左区间端点和右区间的做法,这个做法需要注意几个地方,第一个就是循环的条件,这个不能相等,否则就会一直相等然后死循环,如果有相等的时候就是左右两个左边重合就是相等的,所以这里就是判断中点的时候就需要注意一点,一个是在左边,一个是在右边,在这里就可以进行判断条件了,这里是进行分析,如果是找左边的端点的时候就是不能在给left赋值的时候相等了,同理右端也是,也就是在找右端点的时候右边不能等于,所以这时就可以得出条件了,如下方代码实现,就是左边的时候left=left+1;右边的时候就是righ=right+1;然后根据条件就可以写出代码了。
class Solution { public: vector<int> searchRange(vector<int>& nums, int target) { if(nums.size()==0) return {-1,-1}; int left=0,right=nums.size()-1; int begin=0; while(left<right) { int mid=left+(right-left)/2; if(nums[mid]<target) left=mid+1; else right=mid; } if(nums[left]!=target) return {-1,-1}; else begin=left; left=0,right=nums.size()-1; while(left<right) { int mid=left+(right-left+1)/2; if(nums[mid]<=target) left=mid; else right=mid-1; } return {begin,right}; } };
3、35.搜索插入位置
题目:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例 3:
输入: nums = [1,3,5,6], target = 7
输出: 4
提示:
1 <= nums.length <= 104
-104 <= nums[i] <= 104
nums
为 无重复元素 的 升序 排列数组-104 <= target <= 104
这里先看题目就是查找重复的元素,但是有没有重复的元素,就需要在比这个元素小一个的地方后面插入,也就是如示例2在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(nums[mid]<target) left=mid+1; else right=mid; } if(nums[left]<target) return left+1; return left; } };
4、69.x的平方根
题目:
给你一个非负整数 x
,计算并返回 x
的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5)
或者 x ** 0.5
。
示例 1:
输入:x = 4
输出:2
示例 2:
输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。
提示:
0 <= x <= 231 - 1
这个从题目中可以看出求平方根,所以可以直接在1到x中的数据进行暴力求解,也就是每个都进行平方进行判断,是否等于x,如果大于x的时候,还没找到,就是这个数字的前一个,也就是可以把它当成一个数组,1是left,x是right,然后就可以使用右端点的模板,代码如下方,但是这里需要处理一下,就是x为0的时候就是直接返回0,代码如下。
class Solution { public: int mySqrt(int x) { if(x<1) return 0; int left=1,right=x; while(left<right) { long long mid=left+(right-left+1)/2; if(mid*mid<=x) left=mid; else right=mid-1; } return left; } };