题目:

整数数组 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)-搜索旋转排序数组(中等)的更多相关文章

  1. 33,Leetcode 搜索旋转排序数组-C++ 递归二分法

    题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这 ...

  2. LeetCode(33):搜索旋转排序数组

    Medium! 题目描述: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值 ...

  3. LeetCode(力扣)——Search in Rotated Sorted Array2 搜索旋转排序数组 python实现

    题目描述: python实现 Search in Rotated Sorted Array2 搜索旋转排序数组   中文: 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0 ...

  4. LeetCode(力扣)——Search in Rotated Sorted Array 搜索旋转排序数组 python实现

    题目描述: python实现 Search in Rotated Sorted Array 搜索旋转排序数组   中文:假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1 ...

  5. 力扣Leetcode 33. 搜索旋转排序数组

    33. 搜索旋转排序数组 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值, ...

  6. Java实现 LeetCode 33 搜索旋转排序数组

    33. 搜索旋转排序数组 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值, ...

  7. [leetcode] 33. 搜索旋转排序数组(Java)

    33. 搜索旋转排序数组 说实话这题我连题都没有看懂....真是醉了 二分,没意思,直接交了- - https://www.jiuzhang.com/solutions/search-in-rotat ...

  8. LeetCode:搜索旋转排序数组【33】

    LeetCode:搜索旋转排序数组[33] 题目描述 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2]  ...

  9. Java实现 LeetCode 81 搜索旋转排序数组 II(二)

    81. 搜索旋转排序数组 II 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] ). 编写一个函数来判 ...

  10. 33、搜索旋转排序数组 | 算法(leetode,附思维导图 + 全部解法)300题

    零 标题:算法(leetode,附思维导图 + 全部解法)300题之(33)搜索旋转排序数组 一 题目描述! 题目描述 二 解法总览(思维导图) 三 全部解法 1 方案1 1)代码: // 方案1 & ...

随机推荐

  1. 将Maven和Plugins的源都改为阿里镜像的Setting.xml

    <?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Soft ...

  2. PRD(产品需求文档)与SRS(软件需求规格说明书)的区别

    需求分析是软件开发过程中很重要的一个环节,目前需求分析完成后输出的文档有2种体系,一个是SRS(Software Requirements Specification,软件需求规格说明书),一个是PR ...

  3. 阿里云配置http转https

    参考:https://www.cnblogs.com/alexfly/p/10615986.htmlhttps://www.cnblogs.com/SemiconductorKING/p/910697 ...

  4. Java加密技术(二)——对称加密算法DES&AES

    desdesedejavaaes     接下来我们介绍对称加密算法,最常用的莫过于DES数据加密算法. DES DES-Data Encryption Standard,即数据加密算法.是IBM公司 ...

  5. 标记SA_RESTART的作用

    在程序执行的过程中,有时候会收到信号,我们可以捕捉信号并执行信号处理函数,信号注册函数里有一个struct sigaction的结构体,其中有一个sa_flags的成员,如果sa_flags |= S ...

  6. Android打造万能自定义阴影控件

    目录介绍 01.阴影效果有哪些实现方式 02.实现阴影效果Api 03.设置阴影需要注意哪些 04.常见Shape实现阴影效果 05.自定义阴影效果控件 06.如何使用该阴影控件 07.在recycl ...

  7. 【Docker】Windows将docker下载的镜像存放到其他盘

    1.在D盘创建一个存放docker虚拟机的文件夹,如下面图中所示: 2.创建好以后,找到桌面右下角的docker图标,在上面点右键,选择settings,打开docker的设置界面. 3.然后在doc ...

  8. Java 多级文件夹创建

    File类中的mkdir()和mkdirs(): mkdir():只能创建一层目录.  mkdirs():可以创建多层目录 String path = "E:\\lxwtest\\test& ...

  9. quartus之LPM_DIVIDE

    quartus的IP测试之LPM_DIVIDE 1.基本作用 一个用于除法的IP,可以输入除数.被除数,得到商.余值. 2.基本测试 `timescale 1ns/1ns module divide_ ...

  10. KingbaseES V8R6 运维案例 -- sys_filenode.map故障案例

    ​ 案例说明: 数据库下的sys_filenode.map文件被破坏,导致此数据库无法连接访问. Nail表(内核系统表)Relfilenode的存储机制: 经过研究发现,在数据目录里存在着pg_fi ...