题目:
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
说明:
- 你可以假设
nums
中的所有元素是不重复的。 n
将在[1, 10000]
之间。nums
的每个元素都将在[-9999, 9999]
之间。
示例 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
一、个人分析思路:
二分查找,老生常谈的话题,今天仔细地来分析一下这类题型。总体的思路为:
设定左右两个边界L和R,还有一个中间量M,其中中间量M=floor(L+R)/2;
当左边界的值L不超过R时,
①若当目标值小于中间量时,说明目标值在左侧;
②若当目标值大于中间量时,说明目标值在右侧;
③若当目标值等于中间量时,目标值即为所求。
另外,对于中间量M=floor(L+R)/2,以java语言为例,如下有三种思路
①M=(L+R)/2; //当l+r>Integer.MAX_VALUE,MAX_VALUE的值为20多亿,L+R的相加的结果会导致数值溢出。
②M=L+(R-L)/2; //利用数学公式进行优化,可以避免方法一中的问题
③M=(L+R)>>1; //利用移位运算符,向右移动1位,相比上述方法高效,且不用担心溢出问题。关于移位运算,我的这篇博客做了详细的论述。关于Java中的移位运算:左移<<,右移>>和无符号右移>>>_lollipop的博客-优快云博客移位运算一、前备知识:计算机数据表示(原码、反码和补码)1.1、符号位1.2、对于正数1.3、对于负数1.4、举例二、移位运算2.1、举例2.2、分析2.3、代码验证一、前备知识:计算机数据表示(原码、反码和补码)1.1、符号位对于正数,符号位在最高位用0表示;对于负数,符号位在最高位用1表示;1.2、对于正数原码=反码=补码1.3、对于负数反码=原码的符号位不变,其他位按位取反;补码=反码+1;1.4、举例数值原码反码补码50000 01010000 01https://blog.youkuaiyun.com/xenian_xerus/article/details/121443633 上代码:
class Solution {
public int search(int[] nums, int target) {
int l=0,r=nums.length-1,m;
while(l<=r){
//方法一:当l+r>Integer.MAX_VALUE,会导致数值溢出
// m=(l+r)/2;
//方法二:利用数学公式进行优化,可以避免方法一中的问题
// m=l+(r-l)/2;
//方法三:利用移位运算符,向右移动1位,相比上述方法高效,且不用担心溢出问题
m=(l+r)>>1;
if(nums[m]>target){
r= m-1;
}else if(nums[m]<target){
l = m+1;
}else{
return m;
}
}
return -1;
}
}
最后附上运行结果: