leetcode刷题笔记三十三 搜索旋转排序数组
leetcode刷题笔记三十三 搜索旋转排序数组
源地址:33. 搜索旋转排序数组
问题描述:
假设按照升序排序的数组在预先未知的某个点上进行了旋转。( 例如,数组 [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:
输入: nums = [4,5,6,7,0,1,2], target = 3
输出: -1
代码补充:
//由于要求达到O(logn),对于本题的第一想法就是使用二分法进行查找。
//由于可能存在旋转点,整个有序数组可被分割为一个有序数组或者两个有序数组
//简单的思路是通过对一个或两个有序数组,确认最小值点,即旋转点
//对旋转点两侧进行二分查找
//进一步方法是通过对nums(0)、nums(mid)和target比较
//具体可分为7种情况
//1. target == nums(mid) 这种情况下 return mid
//
//2. tPoint < target && target < nums(mid)
// (tPoint target nums(mid) max)(min .. size-1)
// right = mid -1
//
//3. tPoint <= nums(mid) && nums(mid) <= target
// (tPoint nums(mid) target max)(min .. size-1)
// left = mid + 1
//
//4. nums(mid) < tPoint && target < nums(mid)
//(tPoint .. max)(min target nums(mid) size-1)
// right = mid -1
//
//5. target <= tPoint && nums(mid) <= target
//(tPoint .. max)(min nums(mid) target size-1)
// left = mid + 1
//
//6. target <= tPoint && tPoint <= nums(mid)
//(tPoint nums(id) max)(min target size-1)
//left = mid + 1
//
//7. nums(mid) < tPoint && tPoint < target
//(tPoint target max)(min nums(id) size-1)
//right = mid -1
object Solution {
def search(nums: Array[Int], target: Int): Int = {
if (nums.length == 0) return -1
if (nums.length == 1 && nums(0) != target) return -1
var left = 0
var right = nums.length - 1
val tPoint = nums(0)
var ans = 0
if (nums(left) == target) return left
if (nums(right) == target) return right
while(left <= right){
var mid = (left + right)/2
(tPoint, target, nums(mid)) match {
case s0 if target == nums(mid) => {ans = mid; return ans}
case s1 if (tPoint < target && target < nums(mid)) => {right = mid -1}
case s2 if (tPoint <= nums(mid) && nums(mid) <= target) => {left = mid + 1}
case s3 if (nums(mid) < tPoint && target < nums(mid)) => {right = mid -1}
case s4 if (target <= tPoint && nums(mid) <= target) => {left = mid + 1}
case s5 if (target <= tPoint && tPoint <= nums(mid)) => {left = mid + 1}
case s6 if (nums(mid) < tPoint && tPoint < target) => {right = mid -1}
case _ => return -1
}
}
return -1
}
}
//简化的方法 通过上述方法可以得知我们只需要(nums[0] <= target), (target <= nums[i]) ,(nums[i] < nums[0])
//进行判断
//显然,这三者不可能均不成立或均成立
//所以我们只需要通过异或的方法判断是一个成立,还是二个成立
//两项为真时,向前规约
//一项为真时,向后规约
object Solution {
def search(nums: Array[Int], target: Int): Int = {
var left = 0
var right = nums.length - 1
while(left < right){
var mid = (left + right)/2
if((nums(0) > target) ^ (nums(0) > nums(mid)) ^ (target > nums(mid))) left = mid + 1
else right = mid
}
if (left == right && nums(left) == target) return left
else return -1
}
}