给定一个数组A,当中有一个位置被称为Magic Index,含义是:如果i是Magic Index。则A[i] = i。

如果A中的元素递增有序、且不反复,请给出方法,找到这个Magic
Index。更进一步。当A中同意有反复的元素,该怎么办呢?

没有反复元素的情况

一些同学在遇到这个题目的时候,往往会认为比較简单。扫描一遍,不就ok了么?O(n)的。非常easy呀。但是,大家要注意到,另一个条件没实用:A中的元素是有序递增的。

这个条件,并非放在这里迷惑大家的。而是有更大的作用的。

这个时候,该怎样想呢?O(n)不是最好的方法,更好的是什么呢?怎么利用数组有序呢?在有序的数组中查找一个满足特定元素的条件。我们一般会想到二分查找。 我们来回想一下二分查找,对于要查找的目标t,我们首先与数组中间的元素比較,假设t大于中间的元素,则在右半部分继续查找;假设t小于中间的元素,则在左半部分,继续查找。

那么。我们的题目可以利用上述的思想呢?我们来看一个详细的样例:

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相悖。所以,接下来,仅仅能在右边进行查找。

代码与二分查找也非常像。

详细代码例如以下:

int MagicIndex(vector<int>& data)
{
int begin = 0,end = data.size()-1;
while(begin <= end)
{
int mid = begin + ((end - begin) >> 1);
if(data[mid] > mid)end = mid -1;
else if(data[mid] < mid)begin = mid + 1;
else return mid;
}
return -1;
}

有反复元素的情况

假设数组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    7     8
-10 2 2 2 2 10 12 15 20

这个样例,当我们进行左半部分递归处理的时候。须要考虑的范围是[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    7    8
-10 2 2 2 9 10 12 15 20

此时,要在右半部分进行查找。范围通常是[5, 8]。可是,因为数组有序,后面的值,一定是大于等于A[mid]=9的。

所以。有可能是Magic Index的最小Index是9,也就是说右边的递归。应该是从索引为9的位置開始。此例,就意味着,无需处理右边了。

详细代码例如以下:

int MagicIndexDup(vector<int>& data,int begin,int end)

{

if(begin > end)return -1;

int mid = begin + ((end - begin) >> 1);

if(data[mid] == mid)return mid;

int res = MagicIndexDup(data,begin,min(mid-1,data[mid]));//递归左边

if( res == -1)res = MagicIndexDup(data,max(mid+1,data[mid]),end);//递归右边

return res;

}

int MagicIndexDup(vector<int>& data)

{

return MagicIndexDup(data,0,data.size()-1);

}

待字闺中之Magic Index 分析的更多相关文章

  1. Magic Index 寻找数组中A[i]=i的位置(原题转自微信号待字闺中)

    有一个有意思的题目叫做Magic Index:给定一个数组A,其中有一个位置被称为Magic Index,含义是:如果i是Magic Index,则A[i] = i.假设A中的元素递增有序.且不重复, ...

  2. 算法----Magic Index

    给定一个数组 A,如果 某个下标 i, 满足 A[i] = i, 则 i 称为 Magic Index. 现在假设 A 中的元素是递增有序的.且不重复,找出 Magic Index. 更进一步,当数组 ...

  3. 数组Magic Index

    Question A magic index in an array A[1...n-1] is defined to be an index such that A[i] = i. Given a ...

  4. [8.3] Magic Index

    A magic index in an array A[0...n-1] is defined to be an index such that A[i] = i. Given a sorted ar ...

  5. [CareerCup] 9.3 Magic Index 魔法序号

    9.3 A magic index in an array A[0.. .n-1] is defined to be an index such that A[i] = i. Given a sort ...

  6. 目标用户偏好指数Target Group Index分析

    目标用户偏好指数Target Group Index分析 TGI指数,全称Target Group Index,可以反映目标群体在特定研究范围内强势或者弱势. TGI指数计算公式 = 目标群体中具有某 ...

  7. mongodb query index 分析

    query 的过程及分析: query 是通过Query planner选择最有效的查询plan ,为一个query 被给予一个可用的索引,查询时 query optimizer(最优的查询条件选择器 ...

  8. The Aggregate Magic Algorithms

    http://aggregate.org/MAGIC/ The Aggregate Magic Algorithms There are lots of people and places that ...

  9. ES系列六、ES字段类型及ES内置analyzer分析

    一.背景知识 在Es中,字段的类型很关键: 在索引的时候,如果字段第一次出现,会自动识别某个类型,这种规则之前已经讲过了. 那么如果一个字段已经存在了,并且设置为某个类型.再来一条数据,字段的数据不与 ...

随机推荐

  1. Eigen下载安装

    首先提供Eigen的两个重要网站 官方网站 下载地址 1.下载 wget http://bitbucket.org/eigen/eigen/get/3.3.5.tar.gz 2.解压缩 tar -zx ...

  2. 原生JS封装ajax以及request

    一.封装原生的xhr为ajax类 xhr以及用法见之前的文章 1.根据url确定请求的头部以及别的信息. var _headerConfig = {}; if(url.indexOf('getcapt ...

  3. django-9-请求与响应

    写在表单下面{% csrf_token %} <<<文件上传>>>settings.py UPLOAD_ROOT = os.paht.join(BASE_DIR, ...

  4. 【转】python 关键字

    转自:http://www.cnblogs.com/hongten/p/hongten_python_keywords.html python3.3.2中的关键字如下: The following i ...

  5. UVA 12507 Kingdoms

    D - Kingdoms Time Limit:1000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu A kingdom ha ...

  6. 浅析Mysql InnoDB存储引擎事务原理

    浅析Mysql InnoDB存储引擎事务原理 大神:http://blog.csdn.net/tangkund3218/article/details/47904021

  7. C#一个托付的样例

    C#中的函数能够被声明的一个托付所调用. 函数为静态方法.和托付声明的參数返回值要一致.   class Program { delegate float MathOperationDelegate( ...

  8. Android基础新手教程——1.5.2 Git之使用GitHub搭建远程仓库

    Android基础新手教程--1.5.2 Git之使用GitHub搭建远程仓库 标签(空格分隔): Android基础新手教程 本节引言: 在上一节中.我们学习了怎样使用Git.构建我们的本地仓库.轻 ...

  9. bzoj4568: [Scoi2016]幸运数字(LCA+线性基)

    4568: [Scoi2016]幸运数字 题目:传送门 题解: 好题!!! 之前就看过,当时说是要用线性基...就没学 填坑填坑: %%%线性基 && 神犇 主要还是对于线性基的运用和 ...

  10. bzoj2229: [Zjoi2011]最小割(分治最小割+最小割树思想)

    2229: [Zjoi2011]最小割 题目:传送门 题解: 一道非常好的题目啊!!! 蒟蒻的想法:暴力枚举点对跑最小割记录...绝对爆炸啊.... 开始怀疑是不是题目骗人...难道根本不用网络流?? ...