力扣33(java&python)-搜索旋转排序数组(中等)
题目:
整数数组 nums 按升序排列,数组中的值 互不相同 。
在传递给函数之前,nums 在预先未知的某个下标 k(0 <= 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:
输入:nums = [4,5,6,7,0,1,2], target = 0
输出:4
示例 2:
输入:nums = [4,5,6,7,0,1,2], target = 3
输出:-1
示例 3:
输入:nums = [1], target = 0
输出:-1
提示:
- 1 <= nums.length <= 5000
- -104 <= nums[i] <= 104
- nums 中的每个值都 独一无二
- 题目数据保证 nums 在预先未知的某个下标上进行了旋转
- -104 <= target <= 104
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/search-in-rotated-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路:
【二分查找】
参考:@【liweiwei1419】:https://leetcode.cn/problems/search-in-rotated-sorted-array/solution/er-fen-fa-python-dai-ma-java-dai-ma-by-liweiwei141/ 以及评论区的各位老师!
题目中说将数据进行旋转,这样的话就会将搜索区间从中间一分为二,位于中间的元素nums[mid]一定会在其中一个有序的区间中。由于数组中不存在重复元素,mid与左右两边的元素关系不是小于关系就是大于关系。这里就讨论mid与右边界的大小关系,分为两种情况:
1.mid的值严格大于右边界时:nums[mid] > nums[right]

- 此时在区间[left, mid - 1]内的元素一定是有序的,如果target在[left, mid]里,即nums[left] <= target <=nums[mid],此时设置right = mid - 1;
- 上一个区间的反面,target在区间[mid, right]中,left == mid;
2.mid的值严格小于右边界时:nums[mid] < nums[right]

- 此时在区间[mid, right]内的元素一定是有序的,如果target在[mid, right]里,即nums[mid] <= target <=nums[right],此时设置left = mid ;
- 上一个区间的反面,target在区间[left, mid - 1]中,right == mid - 1;
注意:这里的区间存在[mid, right],为了防止区间只有两个元素的时候,向下取整会让mid一直和left相同,出现死循环,故需要变成向上取整mid = left + (right - left + 1) / 2。
java代码:
1 class Solution {
2 public int search(int[] nums, int target) {
3 int left = 0, right = nums.length - 1;
4 while (left < right){
5 int mid = left + (right - left + 1) / 2;
6 if (target == nums[mid]) return mid;
7 //先根据nums[0]与target判断目标值在mid左端还是右端
8 //在右端,例如[6,7,1,2,3,4,5]
9 if(nums[mid] < nums[right]) {
10 if(target >= nums[mid] && target <= nums[right]){
11 left = mid;
12 }else{
13 right = mid - 1;
14 }
15 }else{
16 //在前部分:[3,4,5,6,7,1,2]
17 if(target <= nums[mid - 1] && target >= nums[left]){
18 right = mid - 1;
19 }else{
20 left = mid;
21 }
22 }
23 }
24 //循环结束的条件:left == right
25 return nums[left] == target ? left : -1;
26 }
27 }

python3代码:
1 class Solution:
2 def search(self, nums: List[int], target: int) -> int:
3 left, right = 0, len(nums) - 1
4 while left <= right:
5 mid = left + (right - left) // 2
6 if nums[mid] == target:
7 return mid
8 # 右边有序
9 # [7,1,2,3,4,5,6]
10 # 取等号是有可能mid == right
11 if nums[mid] <= nums[right]:
12 if nums[mid] < target <= nums[right]:
13 left = mid + 1
14 else:
15 right = mid - 1
16 # 左边有序
17 # [3,4,5,6,7,1,2]
18 # 取等号是有可能mid == left
19 elif nums[mid] >= nums[left]:
20 if nums[left] <= target < nums[mid]:
21 right = mid - 1
22 else:
23 left = mid + 1
24 return -1

说明:
【向上取整】与【向下取整】
向上取整与向下取整主要是为了处理当只剩下两个元素的情况,这时 left 和 right 相差1。
向上取整:把整个区间划分成[left, mid -1] 和 [mid, right],把mid划分给了右区间,如果操作是选择了包含mid的这个区间,那么就需要mid值来更新left,如果向下取整,left和right值算出来的mid就与left相等(例如:(4+5) / 2 == 4),再将left更新成mid,相当于没有更新left,故需要向上取整,算出来的mid值与right相等,这样left向右移动,得到更新,和right指向相同的值。
向下取整:把整个区间划分成[left, mid] 和 [mid + 1, right],把mid划分给了左区间,如果操作是选择了包含mid的这个区间,那么就需要mid值来更新right,如果向上取整,left和right值算出来的mid就与right相等(例如:(5 + 4) / 2 +1 == 5),再将right更新成mid,相当于没有更新right,故需要向下取整,算出来的mid值与left相等,这样right向左移动,得到更新,和left指向相同的值。
总结:
mid如果被分给了右区间,需要向上取整,保证left能够被新值更新。
mid如果被分给了左区间,需要向上取整,保证left能够被新值更新。
力扣33(java&python)-搜索旋转排序数组(中等)的更多相关文章
- 33,Leetcode 搜索旋转排序数组-C++ 递归二分法
题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这 ...
- LeetCode(33):搜索旋转排序数组
Medium! 题目描述: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值 ...
- LeetCode(力扣)——Search in Rotated Sorted Array2 搜索旋转排序数组 python实现
题目描述: python实现 Search in Rotated Sorted Array2 搜索旋转排序数组 中文: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0 ...
- LeetCode(力扣)——Search in Rotated Sorted Array 搜索旋转排序数组 python实现
题目描述: python实现 Search in Rotated Sorted Array 搜索旋转排序数组 中文:假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1 ...
- 力扣Leetcode 33. 搜索旋转排序数组
33. 搜索旋转排序数组 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值, ...
- Java实现 LeetCode 33 搜索旋转排序数组
33. 搜索旋转排序数组 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值, ...
- [leetcode] 33. 搜索旋转排序数组(Java)
33. 搜索旋转排序数组 说实话这题我连题都没有看懂....真是醉了 二分,没意思,直接交了- - https://www.jiuzhang.com/solutions/search-in-rotat ...
- LeetCode:搜索旋转排序数组【33】
LeetCode:搜索旋转排序数组[33] 题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ...
- Java实现 LeetCode 81 搜索旋转排序数组 II(二)
81. 搜索旋转排序数组 II 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判 ...
- 33、搜索旋转排序数组 | 算法(leetode,附思维导图 + 全部解法)300题
零 标题:算法(leetode,附思维导图 + 全部解法)300题之(33)搜索旋转排序数组 一 题目描述! 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: // 方案1 & ...
随机推荐
- C++ 萃取机 Iterator Traits
Iterator Traits 萃取出 Iterator 的性质:迭代器种类.迭代器所指数据类型.迭代器距离类型.迭代器所指数据引用.迭代器所指数据指针.根据不同的迭代器种类可以采取不同的算法策略.但 ...
- [bzoj2120]数颜色/维护队列 (分块)
数颜色/维护队列 [做题笔记] 此生第一道不贺题解\(AC\)的分块蓝题!!! 题目描述 墨墨@hs_mo购买了一套 \(N\) 支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨 ...
- 简单对比Java、Python、Go、Rust等常见语言计算斐波拉契数的性能
前言 最近简单学了下Rust,以我这种菜鸟水平,没感受到什么安全.性能什么方面的优势,只觉得概念太多,编译各种报错.暂时也写不出来什么玩法,索性对比下各种学过的语言的性能.部分语言很早之前学过,很久不 ...
- 记录--H5页面对接微信支付踩坑杂记
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 背景 应用背景:vite搭建的vue3项目 需求背景:功能都涉及了支付业务,故需要和外部支付系统对接 外部支付系统:聚合支付.微信小程序支 ...
- vue3中使用simple-keyboard实现虚拟键盘(带中文切换数字键盘)
效果图 官网 simple-keyboard官网:https://hodgef.com/simple-keyboard/ 打不开的话请用魔法 不足 中文语言包支持度不够.不过自己可以找语言包替换 依赖 ...
- AI实用指南:5分钟搭建你自己的LLM聊天应用
今天,我们将迅速着手搭建一个高效且富有创意的混元聊天应用,其核心理念可以用一个字来概括--快.在这个快节奏的时代,构建一个基础的LLM(Large Language Model,大型语言模型)聊天应用 ...
- KingbaseES 数据插入更新操作
数据库使用过程中,经常会遇到一种场景:业务系统对数据进行dml操作,当数据库中数据不存在时,将数据做为新记录插入到表中,当数据库中数据存在时,对现有数据进行更新操作. 下面介绍KingbaseES中对 ...
- KingbaseES V8R6 运维案例 --ksql访问动态库问题
KingbaseES V8R6数据库运维案例之---ksql访问动态库问题 案例说明: CentOS环境下,在安装和初始化数据库实例后,启动数据库服务,通过ksql连接访问时出现以下故障: 经检查,是 ...
- CDA数据分析师证书一级Level 1 专业备考资料
CDA数据分析师一级Level 1 专业备考资料 包含视频课程+视频配套参考资料,新版大纲,可以边看边学边做笔记. 考试大纲+模拟题+报考指南 + 教材电子书PDF版 关注订阅号[靠谱杨阅读人生]回复 ...
- 使用sbt对Scala程序进行打包并运行(Spark单机运行)
十.使用sbt对Scala程序进行打包并运行(Spark单机运行) 在./sparkapp 中新建文件 simple.sbt(vim ./sparkapp/simple.sbt),添加内容如下,声明该 ...