数组中其余的排除_每日“力扣”系列11 搜索旋转排序数组

今天继续力扣数组标签算法题目,力扣第33题,搜索旋转排序数组,题目等级:中等。

题目描述如下:

1d2d0e53277cbf7555dca5a1052f33a0.png

首先,是来简单分析一下题目:

1、处理过程的输入分为两个部分,第一部分是一个处理过的有序数组,第二部分是一个要在数组中寻找的目标数字。

2、关于处理过的有序数组,处理之前是一个递增的数组,在交给我们之前,数组经历了一次的旋转。这个旋转可以这么来考虑:从数组前连续取几位数字,将之移至数组的末尾,就是一次旋转,例如在题目中的示例 1 中,就是将0 ,1, 2三个数字移至了数组的后部。

3、关于处理过后的输出部分,是一个 int 类型的数字,如果所要寻找的数字在数组中存在,则返回的就是该数字的下标,如果不存在这样一个数字,那就直接返回 - 1.

同时,要求整个的处理过程的时间复杂度为 logN。

通过将上面的题目进行分析,我们可以知道这样几个问题:

首先,由于时间复杂度要求是 logN,那么首先是要选择二分查找法,那如果要使用二分查找,那原数组一定要是有一定规律的,通过上面对“旋转”这一操作的解释,我们可以看出,整个旋转后的数组虽然不一定是整体递增的(说是不一定,可能是将 0 个数字后移,也就想当于没有移动,也就整体仍未升序排列),但是还是可以分为两个升序排列的部分来分别来看。两个部分的交叉点,就是原来么有处理时的最大值与最小值,要区分两个部分,找到这个位置就很关键了。

那分析到这儿,我们的思路就很明确了,概括来说可以分为如下几步:

1、找到“旋转操作的位点”,即后移部分在处理过后的数组中所在位置的启点(也就是示例 1 中的 0 的位置)

2、拿到“位点”,后,数组被分为两个部分两个部分分别都是递增排列的。

3、使用二分查找,在两个部分中查找所要寻找的数字,得到结果(下标或者不存在)

public 

在开始处理之前,先来排除一下特殊情况,节省处理时间,即数组本身无数字(①)或者数字本身就只有一个数字的时候(②)

在排除了数字特殊情况后,根据我们之前的分析,先来寻找“旋转点”,由于原数组整体就是一个递增数组,而这个“旋转”操作就可以看做是将前面的一部分移动到了数组的后面,所以,整个数组,除了“旋转点”前后不是升序排列外,其他部分仍然会保持升序排列,这就是找出这个“旋转点”的依据,具体的实现就是代码中③所做的事情。

在拿到“旋转点”后,如果这个点就是所求,就可以直接返回了(④),否则就分前后两个部分来进行二分查找。

题目中告诉我们,数字不重复,那目标就只会在一个部分中存在,如果可以分开情况来分别进行查找,那一定可以节省循环时间。

我们这里的思路是:既然“旋转”是将一个升序排列的前半部分移动到了后边,那么“旋转”后,第一部分的第一个数字一定会大于第二部分的所有数字。那么我们可以知道,如果目标值target是大于第一个数字的,那么如果在数组中存在,那就会在第一部分,这个时候就只需要在第一部分来进行二分查找了;同理,如果target是小于第一个数字的,那么就只需要在第二部分进行二分查找就OK了。这也就是⑥和⑦的部分所做的事情。

特殊的,当没有数字转移到后边时,整体仍然呈现一个递增趋势,所以就直接对整个数组进行二分查找就OK了。代码中⑤的部分就是啦。

对于用的比价多的二分查找,这里将其包装为一个方法来进行调用(⑧)。

今天的刷题就是这样。

这个系列主要来记录和回滚,如果感觉写的还能看,欢迎转发评论、点赞关注喔

按照惯例,倒一下前两天缩写:

昨天:

王进林:菜鸡刷LeetCode系列记录10 下一个排列​zhuanlan.zhihu.com

前天的两篇:

王进林:菜鸡刷LeetCode系列记录8 删除重复项​zhuanlan.zhihu.com
王进林:菜鸡刷LeetCode系列记录9 移除元素​zhuanlan.zhihu.com

下一天的:

王进林:菜鸡刷LeetCode系列记录12 查找排序数组中的元素范围​zhuanlan.zhihu.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值