来源:力扣(LeetCode) 连接:https://leetcode-cn.com/problems/search-in-rotated-sorted-array算法
假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] )。
搜索一个给定的目标值,若是数组中存在这个目标值,则返回它的索引,不然返回 -1 。
你能够假设数组中不存在重复的元素。
你的算法时间复杂度必须是 O(log n) 级别。
示例 1:数组
输入: nums = [4,5,6,7,0,1,2], target = 0 输出: 4
示例 2:code
输入: nums = [4,5,6,7,0,1,2], target = 3 输出:
在读完一遍题目以后呢,大致的感受是从数组中找到指定值的位置返回,没有的话就返回-1。
而后我就直接写下了排序
var search = function(nums, target) { return nums.indexOf(target); };
运行以后通了,提交以后也通了,执行时间68ms,内存消耗33.7MB。
完美的开始,不过在仔细审题以后,发现一个问题,题目要求复杂度必须是 O(log n)级别,那意思就是必须得使用二分法来作。那么上面的答案就没有意义了。
那么从新开始思考。二分法很简单,就是每次都二分数组,而后在符合条件的数组中进行下一步的二分查找。
将数组一分为二以后,存在两种可能,一边是顺序的,一边是旋转的,那么就须要将target值与左右中间作间隔的值以及两个数组的两端值进行比较。从而判断出要继续在哪一个数组中继续寻找。递归
实例 nums = [4,5,6,7,8,9,0,1,2], target = 0
//设置初试下标值: left=0; right = nums.length; mid = ~~((left + right)/2) //二分数组那么这个时候mid=4 [4,5,6,7] 8 [9,0,1,2]
存在如下几种状况索引
中间值等于目标值,此时能够直接返回mid内存
中间值比目标值target大而且左边数组第一个值小于target,那么说明左边数组是存在旋转的,而且目标值就在这个数组中,这个时候须要继续在左边数组中查找,这个时候left不变,right变成了mid-1;leetcode
中间值比目标值target小而且右边数组最后一个值大于等于target,说明target值在右边数组中,因此须要在右边的数组中继续查找。此时left变成了mid+1,right不变。get
这两种状况下,都是没有肯定值在哪边,因此讲left+1或者right-1进行进一步的查找。
就这样一步一步查找知道最终找到值。用递归能够解决这个问题。io
因此代码以下:
/** * @param {number[]} nums * @param {number} target * @return {number} */ var search = function(nums, target) { var bs = (left,right)=>{ const mid = ~~((left + right)/2); if(left > right)return - 1; if(nums[mid] === target){ return mid; }else if(nums[mid]>target && nums[left] <= target){ return bs(left,mid-1); }else if(nums[mid]>target && nums[left] > target){ return bs(left+1,right); }else if(nums[mid]<target && nums[right]>=target){ return bs(mid+1,right); }else if(nums[mid]<target && nums[right]<target){ return bs(left,right-1); } }; return bs(0,nums.length-1); };
运行结果: 执行时间:68ms 内存消耗:33.9MB