给定一个数组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. 炫酷 CSS 背景效果的 10 个代码片段

    在现代网页设计中,大背景图设计非常流行.随着高清(现在是4K)显示器的出现,越来越多的网页设计师使用大背景图来填充屏幕. 因为这样可以造成很大的视觉冲击力,并有助于更好的传递所要表现的内容. 但是,如 ...

  2. word上怎么打钩

    原文:http://www.wordlm.com/html/2291.html 有时我们在Word中制作一份特殊的表格时,可能会用到这样一些特殊符号,“在方框里打钩”或打叉.这些符号虽看起来简单不起眼 ...

  3. 【2018 Multi-University Training Contest 2 1007】Naive Operations

    [链接] 我是链接,点我呀:) [题意] 给你两个数组a,b; b数组是1..n的一个排列. 现在给你两种操作: add l,r将a[l..r]都加上1 query l,r 询问$∑^r_l\frac ...

  4. 利用新版本自带的Zookeeper搭建kafka集群

    安装简要说明新版本的kafka自带有zookeeper,其实自带的zookeeper完全够用,本篇文章以记录使用自带zookeeper搭建kafka集群.1.关于kafka下载kafka下载页面:ht ...

  5. POJ 1281 MANAGER

    MANAGER Time Limit:1000MS    Memory Limit:10000KB    64bit IO Format:%I64d & %I64u Description O ...

  6. mysql数据库连接工具类C3P0

    package com.dl.network_flow.db; import java.sql.Connection; import java.sql.PreparedStatement; impor ...

  7. Residual Networks &lt;2015 ICCV, ImageNet 图像分类Top1&gt;

    本文介绍一下2015 ImageNet中分类任务的冠军--MSRA何凯明团队的Residual Networks.实际上.MSRA是今年Imagenet的大赢家.不单在分类任务,MSRA还用resid ...

  8. m_Orchestrate learning system---八、下拉列表(select标签)如何实现链接功能

    m_Orchestrate learning system---八.下拉列表(select标签)如何实现链接功能 一.总结 一句话总结:option的值就是链接地址,选择事件为指向选中的option的 ...

  9. javascript系列-class2.javascript 基本使用

    欢迎加入前端交流群来py: 转载请标明出处!     逻辑运算             一门计算机语言,编程的核心在于逻辑思想,当我们在编写程序的时候,逻辑是否通顺,是能否正确写出程序的关键,可以说如 ...

  10. 在ubuntu下访问windows硬盘出现错误:Error mounting /dev/sda7 at /media

    在终端输入以下代码: sudo apt-get install ntfs-3g sudo ntfsfix /dev/sda7 运行完后: 这样就可以成功访问了.