LeetCode 33. 搜索旋转排序数组 Search in Rotated Sorted Array(C语言)

题目描述:

假设按照升序排序的数组在预先未知的某个点上进行了旋转。
( 例如,数组 [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

题目解答:

方法1:二分法

主要有两大种情况,第一种从beginend之间是没有出现旋转的,即单调递增,此时使用正常的二分法就可以搜索目标数;另一种就是出现了旋转,发生了断裂。后者中,mid可能位于左半支(断裂位置前边),也可能位于右半支(断裂位置后边),所以分情况考虑。假设位于左半支,如果target位于nums[begin]nums[mid]之间,则搜索区间就在beginmid + 1之间,反之在mid + 1end之间;位于右半支同理。需要注意的是nums[mid]可能与nums[begin]nums[end]相等。
运行时间4ms,代码如下。

int search(int* nums, int numsSize, int target) {
    int i = 0, j = numsSize - 1, m = 0;
    while(i <= j) {
        m = (i + j) / 2;
        if(nums[m] == target)
            return m;
        if(nums[i] <= nums[m] && nums[i] > nums[j]) {
            if(nums[i] <= target && target < nums[m])
                j = m - 1;
            else
                i = m + 1;
        }
        else if(nums[m] < nums[j] && nums[i] > nums[j]) {
            if(nums[m] < target && target <= nums[j])
                i = m + 1;
            else
                j = m - 1;
        }
        else {
            if(nums[m] < target)
                i = m + 1;
            else 
                j = m - 1;
        }
    }
    return -1;
}

方法2:确定旋转位置

先通过二分法确定找数组的最大值或者最小值,来确定旋转的位置;然后根据旋转的位置,进行二分法确定目标数是否存在。其中m表示原本的位置,nowMid表示旋转后的位置。
运行时间4ms,代码如下。

int search(int* nums, int numsSize, int target) {
    if(numsSize == 0)
        return -1;
    int i = 0, j = numsSize - 1, m = 0;
    int rot = 0;
    // 通过找最小值确定旋转位置
    // while(i < j) {
    //     m = (i + j) / 2;
    //     if(nums[m] > nums[j])
    //         i = m + 1;
    //     else
    //         j = m;
    // }
    // rot = i;
    // 通过找最大值确定旋转位置
    while(i < j) {
        m = (i + j) / 2 + 1;
        if(nums[m] >= nums[i])
            i = m;
        else
            j = m - 1;
    }
    rot = i + 1;
    
    i = 0;
    j = numsSize - 1;
    while(i <= j) {
        m = (i + j) / 2;
        int nowMid = (m + rot) % numsSize;
        if(nums[nowMid] == target)
            return nowMid;
        else if(nums[nowMid] < target)
            i = m + 1;
        else
            j = m - 1;
    }
    return -1;
}

你可能感兴趣的:(LeetCode,C语言)