Magic Index 寻找数组中A[i]=i的位置(原题转自微信号待字闺中)
有一个有意思的题目叫做Magic Index:给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i。假设A中的元素递增有序、且不重复,请给出方法,找到这个Magic Index。更进一步,当A中允许有重复的元素,该怎么办呢?
一般情况下这种题目一看没有多复杂的时间复杂度,直接扫描一边数组就好了,O(n),当我们认识读题目的时候发现有个体检没有用到就是这个“数组元素递增有序,不重复”,这句话会不会给我们带来捷径呢,事实是可以的。通常在有序的数组中查找满足条件的元素,我们通常会想到二分法。这里不再啰嗦二分法的思想了。
那么,我们的题目能够利用上述的思想呢?我们来看一个具体的例子:
0 1 2 3 4 5 6
-10 -5 1 2 4 10 12
mid=3,A[mid] = 2,即A[mid] < mid。接下来,我们应该在哪一边查找呢?我们知道数组的元素是递增有序,且不重复的,也就是说,在A[mid]左边的元素,比A[mid]都要小,没有重复,意味着什么呢?每向左移动一位,至少减1。所以,在mid左边,不可能有一个i,A[i]=i的。如果有,根据前面的分析,我们知道A[mid] - A[i] >= mid - i, 如果A[i] = i,则,A[mid] >= mid, 这与事实A[mid] < mid相悖。所以,接下来,只能在右边进行查找。代码与二分查找也很像。
有重复元素的情况
如果数组A中,有重复元素,是什么情况呢?经过前面的分析,我们知道,是否有重复的主要差别在,数组的元素从右到左进行递减,每次不一定至少是1了,有可能是0了。让我们直观的看一下影响吧。
0 1 2 3 4 5 6
-10 2 2 2 9 10 12
看上面的数组,同样A[mid] < mid。我们应该继续查右边么?显然,右边并不存在Magic Index。查找右边,就会找不到这样的Magic Index。此时,应该如何处理呢?我们无法确定,Magic Index是在左边,还是在右边了。那就两边都递归进行处理吧。
在这里还有一个小技巧,我们就是要分别递归处理[0, mid - 1]和[mid + 1, end](end是数组长度-1)么?我们看一个具体的例子:
0 1 2 3 4 5 6
-10 2 2 2 2 10 12
这个例子,当我们进行左半部分递归处理的时候,需要考虑的范围是[0, 3]。可实际上,我们只需要考虑[0, 2]。原因是,数组元素在mid=4的左边的值都要小于或者等于A[mid]=2,所以最大的一个有可能是Magic Index的,就是index为A[mid]的情况。所以,这时右边的边界应该是min(mid - 1, A[mid])。
那么,右边的情况呢?如下例子:
0 1 2 3 4 5 6
-10 2 2 2 9 10 12
此时,要在右半部分进行查找,范围一般是[5, 8]。但是,由于数组有序,后面的值,一定是大于等于A[mid]=9的。所以,有可能是Magic Index的最小Index是9,也就是说右边的递归,从max(mid+1,A[mid])开始查找,本题应该是从索引为9的位置开始。此例,就意味着,无需处理右边了。
Magic Index 寻找数组中A[i]=i的位置(原题转自微信号待字闺中)的更多相关文章
- 寻找数组中的第K大的元素,多种解法以及分析
遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因 ...
- [经典算法题]寻找数组中第K大的数的方法总结
[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据 ...
- 寻找数组中第K大数
1.寻找数组中的第二大数 using System; using System.Collections.Generic; using System.Linq; using System.Text; u ...
- Java实现 蓝桥杯 算法训练 寻找数组中最大值
算法训练 寻找数组中最大值 时间限制:1.0s 内存限制:512.0MB 提交此题 问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于10 ...
- C#中使用IndexOf()判断字符串在字符串数组中第一次出现的索引位置
] {"}; "; //判断字符串的前几位在另一个字符串数组中第一次出现的索引位置 index = Array.IndexOf(s, s1.Substring(, ));
- 交换数组中两个元素的位置,元素包括key和value 一维数组
/*author: yangyu@sina.cndescription: 交换数组中两个元素的位置,元素包括key和value,具体用法见下面的例子*/$arr = array(11=>'a', ...
- 寻找数组中第K频繁的元素
问题是:给你一个数组,求解出现次数第K多的元素.当然leetcode上的要求是算法复杂度不能大于O(N*logN). 首先这个问题我先是在leetcode上看到,当时想了两种做法,做到一半都觉得不是很 ...
- 窥探算法之美妙——寻找数组中最小的K个数&python中巧用最大堆
原文发表在我的博客主页,转载请注明出处 前言 不论是小算法或者大系统,堆一直是某种场景下程序员比较亲睐的数据结构,而在python中,由于数据结构的极其灵活性,list,tuple, dict在很多情 ...
- 2.10 用最少次数寻找数组中的最大值和最小值[find min max of array]
[本文链接] http://www.cnblogs.com/hellogiser/p/find-min-max-of-array.html [题目] 对于一个由N个整数组成的数组,需要比较多少次才能把 ...
随机推荐
- Harbor私有仓库搭建
1.安装docker yum install -y dockersystemctl start dockersystemctl enable docker 2.安装docker-compose 1.下 ...
- php……流程
流程:由两个及以上的业务步骤,完成一个完整的业务行为的过程,可称之为流程:注意是两个及以上的业务步骤.事物进行过程中的次序或顺序的布置和安排. 创建页面: 登录页面(login.php): <h ...
- php任务管理器 —— Jobby
通过一个主crontab任务去维护别的任务 自定义的计划任务完全由PHP编写 任务的执行计划时间表设置与crontab的时间表设置语法一致 在指定的时间内只会运行一个任务 邮件告警异常退出任务 在ro ...
- Ubuntu: 无法使用su命令
Ubuntu 无法使用su命令解决方案 在Ubuntu上编译Qt环境时发现无法使用su命令切换到root用户,通过网上查找发现解决方案如下: xt@xt-ubuntu:~$ su密码: su:认证失败 ...
- 重置密码解决MySQL for Linux错误 ERROR 1045 (28000)
重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using passwor ...
- 汽车AC键到底是干什么的?老司机告诉你
现在很多人都会开车,想我当初学车的时候一会就可以上手了,开车简单,但是很多细节方面的就是得慢慢学习的过程,比如说汽车的AC键,我相信很多车主,包括老司机都不知道到底有哪些作用,只知道开空调,其实它的用 ...
- Luogu-4248 [AHOI2013]差异
\(\sum_{i<j}len(i)+len(j)\)比较简单,稍微想想就出来了,问题在于怎么求任意两个后缀的\(lcp\)长度之和 因为求\(lcp\)实际上就是一个对\(h\)数组求区间最小 ...
- 派派和京东的paipai域名之争
最近有一款叫“派派”的APP很火,微博上.电梯里.群里到处都是推广广告.不仅如此,还有大张伟.关晓彤.王祖蓝等十几个明星发帖为“派派”站台.有消息称,派派这段时间仅线上推广就花去了约1600万. 总融 ...
- JavaScript中有时候需要获取当前的时间戳
JavaScript中有时候需要获取当前的时间戳信息,下面列举了三种获取当前时间戳的方法,第一种方法只精确到秒,后两种方法精确到毫秒. 第一种方法 var timestamp1 = Date.pars ...
- android、ipone在文本框中输入文字的不同
1.android机会输入时会在键盘上先显示,你确定后再填充如文本框 2.ipone机是你输入时就直接填充到文本框,当你选择输入信息时,就会先把文本框的内容清空,在填充选择的文字,这时就会有个问题,如 ...