Search in Rotated Sorted Array

原题链接Search in Rotated Sorted Array

一个无重复项的递增序列右移了一定距离,在右移后的序列中查找是否有某个元素
比如[0,1,2,4,5,6,7]右移4位变为[4,5,6,7,0,1,2],在[4,5,6,7,0,1,2]中查找某个元素,事先不知道移动了多少位


对于有序序列,首先可以想到的是利用二分法查找,但是序列别移动后的起点不再是最左边的位置。比如说上面的例子,起点0在下标为4的位置,所以不一定满足nums[0] < nums[n - 1],不能直接使用二分法。
但是因为是整体移动,局部仍然是有序的,所以如果确定了某个区间是有序的,那么还是可以使用二分法的

下面的*代表起点

o   *   o   o   o   o   o
大          小          中
left       middle      right
如果起点在middle的左侧,那么nums[left],nums[middle],nums[right]的大小关系如上
可通过nums[middle] < nums[right]判断起点在middle左边o   o   o   o   o   *   o
中          大          小
left       middle      right
如果起点在middle的右侧,那么nums[left],nums[middle],nums[right]的大小关系如上
可通过nums[middle] > nums[right]判断起点在middle右边

以第一种情况为例(起点在middle左侧)即nums[middle] < nums[right]
如果目标元素在[middle, right]区间,那么一定有nums[target] >= nums[middle] && nums[target] <= nums[right]
否则,目标元素在[left, middle]区间内
因为[middle, right]一定是递增的,所以可以判断目标元素是否在这个区间内,而[left, middle]区间不是递增的,故不能判断。

第二种情况同理
代码如下

class Solution {
public:int search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while(left < right){int middle = (left + right) / 2;if(nums[middle] == target)return middle;/* 第一种情况,起点在middle左边 */if(nums[middle] < nums[right]){/* 目标在[middle, right]区间,因为nums[middle]已经比较过了,所以middle不需要等号 */if(target > nums[middle] && target <= nums[right])left = middle + 1;elseright = middle - 1;}/* 第二种情况,起点在middle右边 */else{/* 目标在[left, middle]区间,middle不需要等号,原因同上 */if(target < nums[middle] && target >= nums[left])right = middle - 1;elseleft = middle + 1;}}return left < nums.size() && nums[left] == target ? left : -1;}};

扩展
原题链接Search in Rotated Sorted Array II

要求和上面的一样,只是所给序列可能带有重复项。
此时情况就不仅仅是上面两种,比如

o   o   o   o   o   *   o
小          小  大       小
left       middle      right
如果起点在middle的右侧,那么有可能nums[middle] == nums[right]

[3,1,1]中找3为例
此时nums[middle] == nums[right],那么通过上面的方法判断得知起点在右边(进入else),但是此时[left, middle]不是递增的。而上面的方法必须保证

  • 如果起点在右边,那么[left, middle]是递增的
  • 如果起点在左边,那么[middle, right]是递增的

解决办法是通过比较nuns[middle] < nums[right]判断起点在左边,比较nums[middle] > nums[right]判断起点在右边,否则有重复项,将right左移,重新判断。

为什么左移right
因为nums[middle] == nums[right],可知存在重复项,那么无法保证[left, middle]是递增的,所以缩小范围,将区间变为[left, right-1],尝试去掉重复项。

代码如下

class Solution {
public:bool search(vector<int>& nums, int target) {int left = 0;int right = nums.size() - 1;while(left < right){int middle = (left + right) / 2;if(nums[middle] == target)return true;/* 起点在左边 */if(nums[middle] < nums[right]){if(target > nums[middle] && target <= nums[right])left = middle + 1;elseright = middle - 1;}/* 起点在右边 */else if(nums[middle] > nums[right]){if(target < nums[middle] && target >= nums[left])right = middle - 1;elseleft = middle + 1;}/* 有重复项 */else{--right;}}return left < nums.size() && nums[left] == target ? true : false;}
};

每天一道LeetCode-----有序数组右移n位后查找某个元素相关推荐

  1. 字符串右移n位,例如 “hello world“ 右移两位 后ldhello wor 要求写一个方法实现此功能,方法的格式是 String moveToRight(String str,int po

    字符串右移n位,例如 "hello world" 右移两位 后ldhello wor 要求写一个方法实现此功能,方法的格式是 String moveToRight(String s ...

  2. LeetCode4寻找两个有序数组的中位数(二分查找+分治)

    目录 1.题目 2.分析 3.代码 二分查找:绝大多数二分查找问题利用的是单调性,也有一些例外)或者题目本身蕴含的可以逐渐缩小问题规模的特性解决问题.时间复杂度log级. 分治法的设计思想是:将一个难 ...

  3. ⭐算法入门⭐《哈希表》中等05 —— LeetCode 215. 数组中的第K个最大元素

    文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 2.时间复杂度 3.代码详解 三.本题小知识 四.加群须知 一.题目 1.题目描述   给定整数数组nums和 ...

  4. 每天一道LeetCode-----有序数组循环右移n位后,寻找最小值,数组中可能包含重复元素

    Find Minimum in Rotated Sorted Array II 原题链接Find Minimum in Rotated Sorted Array II 一个有序数组循环右移n位,找到右 ...

  5. 每天一道LeetCode-----从有序数组中删除重复元素

    Remove Duplicates from Sorted Array 原题链接Remove Duplicates from Sorted Array 给定一个有序数组,对于数组中的重复项,只需要保留 ...

  6. LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)

    文章目录 1. 题目 2. 解题 2.1 合并数组 2.2 优化2.1解法,双指针 2.3 二分法(找第k个数) 2.4 切分法 1. 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 n ...

  7. 求两个有序数组的中位数或者第k小元素

    问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...

  8. 字符串右移n位,例如 “hello world“ 右移两位 后ldhello wor

    public static void main(String[] args) {String a = "hello world";System.out.println( test( ...

  9. 力扣(LeetCode)215. 数组中的第K个最大元素(C语言)

    一.环境说明 本文是 LeetCode 215题 : 数组中的第K个最大元素,使用c语言实现. 快速选择.查找无序数组的利器! 测试环境:Visual Studio 2019. 二.代码展示 void ...

最新文章

  1. 火箭队老板成比特币粉丝 旗下豪车经销商接受BTC、BCH支付
  2. 重温JavaScript
  3. onedrive目录PHP源码,另一个OneDrive目录索引应用 OLAINDEX
  4. Win7重启后IP地址无效
  5. 数据特征分析-对比分析
  6. [html] HTML5的Server-Sent和WebSocket如何选择哪一个?
  7. 在Word中如何实现后退?
  8. eclipse php 代码风格,关于更改Zend Studio/Eclipse代码风格主题的介绍
  9. iwrite提交不了作业_痛点!为什么开发了那么多软件,还是解决不了教学问题!...
  10. haartraining生成.xml过程
  11. 软件工程——软件需求分析
  12. 分享一个经验模态分解分解视频,讲的超好
  13. postgresql查看锁表的进程
  14. NTC功率型热敏电阻
  15. Oreilly的历史和公司概况
  16. Android初学者的疑惑与“死板”的Android初学之路
  17. Kruskal vs Borůvka
  18. C++学习记录3:定义一个矩形类Rectangle
  19. NEON intrinsics 函数模式介绍
  20. css span文字下划线

热门文章

  1. 显卡在电脑什么位置_告诉你什么配置的电脑显卡/GPU才能播放4K电影视频
  2. LAMP之Apache
  3. TCP/IP详解学习笔记(2)-数据链路层
  4. 算法训练 出现次数最多的整数
  5. OWASP出品:Xenotix XSS漏洞测试框架及简单使用
  6. 回首经典的SQL Server 2005
  7. 单击GridView进入编辑模式
  8. PHP-代码审计-文件包含
  9. kali linux 设置固定IP地址步骤
  10. 【数据结构与算法】之深入解析“冗余连接”的求解思路与算法示例