力扣热题100 - 二分查找 - 做了python、C++入门资料现在免费下载:搜索旋转排序数组 - 经典后端开发面试题

本题是二分搜索的变体,在后端开发岗位的面试中出现频率较高。在此将题解分享给大家。

python、C++入门资料领取,目前在本平台:

1、进入本博客主页

2、在 资源 中可以下载它们

今天的题目:

题目描述:

题号:34

整数数组 nums 按升序排列,数组中的值 互不相同 。

在传递给函数之前,nums 在预先未知的某个下标 k0 <= k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]](下标 从 0 开始 计数)。例如, [0,1,2,4,5,6,7] 在下标 3 处经旋转后可能变为 [4,5,6,7,0,1,2] 。

给你 旋转后 的数组 nums 和一个整数 target ,如果 nums 中存在这个目标值 target ,则返回它的下标,否则返回 -1 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

图片

解题思路:

思路一:二分查找 + 判断是否有序

1、初始化两个指针,left指向数组的起始位置,right指向数组的末尾位置。

2、进入循环,当left小于等于right时执行以下步骤:

计算中间位置mid,mid = left + (right - left) / 2,防止整数溢出。

如果nums[mid]等于target,则找到目标值,返回mid。

判断哪一部分是有序的,并根据有序部分确定下一步的查找范围:

(1)如果nums[left]到nums[mid]是有序的:

  • 如果target在nums[left]到nums[mid]之间,则将right更新为mid - 1,继续在左半部分查找。

  • 否则,将left更新为mid + 1,继续在右半部分查找。

(2)如果nums[mid]到nums[right]是有序的:

  • 如果target在nums[mid]到nums[right]之间,则将left更新为mid + 1,继续在右半部分查找。

  • 否则,将right更新为mid - 1,继续在左半部分查找。

3、如果循环结束仍未找到目标值,则返回-1,表示目标值不存在于数组中。

时间复杂度:O(log n) 

空间复杂度:O(1)

C++


// C++
class Solution {
public:
    int search(vector<int>& nums, int target) {
        int left = 0, right = nums.size() - 1;  
        
        while (left <= right) {  
            int mid = left + (right - left) / 2;  
            
            if (nums[mid] == target) {  
                return mid;  
            }  
            
            if (nums[left] <= nums[mid]) {  
                if (nums[left] <= target && target < nums[mid]) {  
                    right = mid - 1;  
                } else {  
                    left = mid + 1;  
                }  
            } else {  
                if (nums[mid] < target && target <= nums[right]) {  
                    left = mid + 1;  
                } else {  
                    right = mid - 1;  
                }  
            }  
        }  
        
        return -1;  
    }
};

go


// go
func search(nums []int, target int) int {  
    left, right := 0, len(nums)-1  
      
    for left <= right {  
        mid := left + (right - left) / 2  
          
        if nums[mid] == target {  
            return mid  
        }  
          
        if nums[left] <= nums[mid] {  
            if nums[left] <= target && target < nums[mid] {  
                right = mid - 1  
            } else {  
                left = mid + 1  
            }  
        } else {  
            if nums[mid] < target && target <= nums[right] {  
                left = mid + 1  
            } else {  
                right = mid - 1  
            }  
        }  
    }  
      
    return -1  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值