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
    }
}
原文地址:https://www.cnblogs.com/ganshuoos/p/12846853.html