每天一道LeetCode-----有序数组右移n位后查找某个元素
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位后查找某个元素相关推荐
- 字符串右移n位,例如 “hello world“ 右移两位 后ldhello wor 要求写一个方法实现此功能,方法的格式是 String moveToRight(String str,int po
字符串右移n位,例如 "hello world" 右移两位 后ldhello wor 要求写一个方法实现此功能,方法的格式是 String moveToRight(String s ...
- LeetCode4寻找两个有序数组的中位数(二分查找+分治)
目录 1.题目 2.分析 3.代码 二分查找:绝大多数二分查找问题利用的是单调性,也有一些例外)或者题目本身蕴含的可以逐渐缩小问题规模的特性解决问题.时间复杂度log级. 分治法的设计思想是:将一个难 ...
- ⭐算法入门⭐《哈希表》中等05 —— LeetCode 215. 数组中的第K个最大元素
文章目录 一.题目 1.题目描述 2.基础框架 3.原题链接 二.解题报告 1.思路分析 2.时间复杂度 3.代码详解 三.本题小知识 四.加群须知 一.题目 1.题目描述 给定整数数组nums和 ...
- 每天一道LeetCode-----有序数组循环右移n位后,寻找最小值,数组中可能包含重复元素
Find Minimum in Rotated Sorted Array II 原题链接Find Minimum in Rotated Sorted Array II 一个有序数组循环右移n位,找到右 ...
- 每天一道LeetCode-----从有序数组中删除重复元素
Remove Duplicates from Sorted Array 原题链接Remove Duplicates from Sorted Array 给定一个有序数组,对于数组中的重复项,只需要保留 ...
- LeetCode 4. 寻找两个有序数组的中位数(二分查找,难)
文章目录 1. 题目 2. 解题 2.1 合并数组 2.2 优化2.1解法,双指针 2.3 二分法(找第k个数) 2.4 切分法 1. 题目 给定两个大小为 m 和 n 的有序数组 nums1 和 n ...
- 求两个有序数组的中位数或者第k小元素
问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 设两个数组分别是vec1和vec2,元素数目分别是n1.n2. 算法1:最简单的办法就是把两个数 ...
- 字符串右移n位,例如 “hello world“ 右移两位 后ldhello wor
public static void main(String[] args) {String a = "hello world";System.out.println( test( ...
- 力扣(LeetCode)215. 数组中的第K个最大元素(C语言)
一.环境说明 本文是 LeetCode 215题 : 数组中的第K个最大元素,使用c语言实现. 快速选择.查找无序数组的利器! 测试环境:Visual Studio 2019. 二.代码展示 void ...
最新文章
- 火箭队老板成比特币粉丝 旗下豪车经销商接受BTC、BCH支付
- 重温JavaScript
- onedrive目录PHP源码,另一个OneDrive目录索引应用 OLAINDEX
- Win7重启后IP地址无效
- 数据特征分析-对比分析
- [html] HTML5的Server-Sent和WebSocket如何选择哪一个?
- 在Word中如何实现后退?
- eclipse php 代码风格,关于更改Zend Studio/Eclipse代码风格主题的介绍
- iwrite提交不了作业_痛点!为什么开发了那么多软件,还是解决不了教学问题!...
- haartraining生成.xml过程
- 软件工程——软件需求分析
- 分享一个经验模态分解分解视频,讲的超好
- postgresql查看锁表的进程
- NTC功率型热敏电阻
- Oreilly的历史和公司概况
- Android初学者的疑惑与“死板”的Android初学之路
- Kruskal vs Borůvka
- C++学习记录3:定义一个矩形类Rectangle
- NEON intrinsics 函数模式介绍
- css span文字下划线