题解 | #在旋转过的有序数组中寻找目标值#
在旋转过的有序数组中寻找目标值
http://www.nowcoder.com/practice/87c0e7abcbda41e7963660fa7d020995
描述
给定一个整数数组nums,按升序排序,数组中的元素各不相同。
nums数组在传递给search函数之前,会在预先未知的某个下标 t(0 <= t <= nums.length-1)上进行旋转,让数组变为[nums[t], nums[t+1], ..., nums[nums.length-1], nums[0], nums[1], ..., nums[t-1]]。
比如,数组[0,2,4,6,8,10]在下标3处旋转之后变为[6,8,10,0,2,4]
现在给定一个旋转后的数组nums和一个整数target,请你查找这个数组是不是存在这个target,如果存在,那么返回它的下标,如果不存在,返回-1
示例1
输入: [6,8,10,0,2,4],10 返回值: 2
示例2
输入: [6,8,10,0,2,4],3 返回值: -1
示例3
输入: [2],1 返回值: -1
思路
在有序数组中找某个数字,最常用的方法就是 二分查找,这道题唯一的不同就是会旋转字符串的某部分,会导致字符串部分有序,不过这并不影响 二分查找 的使用。
当找到 mid 位置时,判断 0 - mid 是否时有序的,如果是有序的,则去判断 target 是否在 0 - mid 中,如果在的话,更新 end = mid - 1就行;如果不在 则更新 start = mid + 1,和 二分查找原理很相似,只这次不过先判断是否有序,在判断目标值是否在区间内。
AC 代码
public int search (int[] nums, int target) { // write code here if (nums == null || nums.length < 1) { return -1; } if (nums.length == 1) { return nums[0] == target ? 0 : -1; } int start = 0, end = nums.length - 1; while (end >= start) { // 找到 左右指针中间位置 int mid = (end + start) >> 1; if (nums[mid] == target) { return mid; } // 在左侧升序数组中 if (nums[0] <= nums[mid]) { // 在开头和 mid 之间,那么 右指针则为 mid -1 if (target >= nums[0] && target < nums[mid]) { end = mid -1; } else { start = mid + 1; } } else { // 如果在 mid 和end 之前,更新 start 为 mid = 1 if (target > nums[mid] && target <= nums[end]) { start = mid + 1; } else { end = mid - 1; } } } return -1; }
时间复杂度: O(logn),其中 n 为 nums 数组的大小。整个算法时间复杂度即为二分查找的时间复杂度 O(logn)。
空间复杂度: O(1) 。
最后
这道题虽然是部分有序的,但是依然使用 二分查找 为核心思想。
大家可以去 【牛客网-题库-在线编程】去练习一下。
可以去微信搜索:【蘑菇睡不着】交个朋友~
也可以扫描下方二维码。
AC 算法题