高效的算法找出中间所有A[i] = i的下标

给定一个排好升序的数组A[1]、A[2]、……、A[n],其元素的值都两两不相等。请设计一高效的算法找出中间所有A[i]
= i的下标。并分析其复杂度。

解析:首先分析一下这个数组,假设其中某个位置的A[i] = i,那么可以肯定的值,之前的A[x] > x,之后的A[x] < x。还有一个显而易见的性质就是中间的A[i]=i一定是连续存在的,不可能跨区域存在,因为这个数组是升序的。

我给出的方法是二分查找,具体的做法是:我们假设一个新数组B,其元素是A[i] - i的值,这样的话,B[i] = 0的时候A[i] = i,而且把B数组划分成了三个部分,左边的小于零的区域,中间的等于零的区域,右边的大于零的区域。

我第一次的想法是:二分搜索这个想象中的新数组,找到值为零的下标,但是这个下标不一定是最左边的满足条件的下标,所以我们还需要写一个while来往左移动这个下标,直到找到最左边的符合条件的下标,如下代码(假设已经通过二分查找找到了符合条件的一个下标idx):


1

2

while(A[idx-1]
== (idx-1))

     idx--;

这样的话其时间复杂度就是O(logn) + O(n),还是属于On)的范畴。

后来我想到,为什么只去随机命中一个目标下标呢!如果二分查找这个数据的边界的话,就能直接得到最左边符合条件的下标了!其实二分查找不仅仅适用于对一个元素的搜索,也可以用于两个、三个特定相对位置元素的搜索。每次查找的时候,假设当前位置是mid,那么只要判断当前A[mid] - mid是否小于零,以及后一个元素A[mid+1] - (mid+1) == 0就行了。

#include 
<iostream> 

usingnamespace

std; 

  

intBinarySearch(intcc[], intlen) 

   intl
= 0, r = len, mid; 

   while(l
<= r) 

   

      mid
= l + ((r-l) >> 1); 

      if(mid
== 0 && cc[mid] == mid)   
//
若数组一开始就符合条件 

         return0; 

      //
若满足条件的下标不是从0开始,则边界是前一个<0,且后一个=0 

      if(cc[mid]-mid
< 0 && cc[mid+1]-(mid+1) == 0) 

         returnmid+1; 

      //
二分查找边界:前一个<0,且后一个=0 

      if(cc[mid]
- mid >= 0) 

         r
= mid-1; 

      else

         l
= mid+1; 

   

   return-1; 

  

intmain() 

   //
int cc[] = {0, 1}; 

   //
int cc[] = {0, 1, 2, 3, 4, 5, 6, 7}; 

   //
int cc[] = {-9, -8, -4, -2, 4, 5, 9}; 

   //
int cc[] = {-5, -4, -3, 5, 6, 7}; 

   intlen
sizeof(cc)/sizeof(int); 

   intidx
= BinarySearch(cc, len); 

   if(idx
!= -1) 

   

      while(cc[idx]
== idx) 

      

         printf("%d
"
,
idx); 

         idx++; 

      

   

   else

   

      printf("Not
found\n"
); 

   

  

   getchar(); 

   return0; 

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-12 14:44:57

高效的算法找出中间所有A[i] = i的下标的相关文章

[算法]找出数组当中的中枢元素

给定一个整型数组,找出pivot,使得对于任意i < pivot,a[i] <=a[pivot],对于i > pivot,a[i]>=a[pivot],只能用一个额外的数组,和少量空间. 思路 1.使用一个数组t记录,t[i]记录的是a[0]~a[i]的最大值 int *t = new int[n]; for(int i = 0, max = ~0; i < n; ++i){ if(a[i] > max){ max = a[i]; } t[i] = max; } 2.从

数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数

问题描述: 数组a[n]中存放1-n中的n-1个数,给出算法找出重复的那一个数. 算法一: 对数组a[n]进行冒泡排序,如果冒泡所得的最值和前一个最值相等,则该最值为重复的数. 分析: 该算法时间复杂度最坏的情况为O(n的2次方),在空间开销上只需要一个额外的交换空间. 如何将时间开销减小呢?下面给出另外一种算法 算法二: 给定另外一个数组b[n],将a[n]中的数作为数组b的索引,然后遍历b[n],如果未访问过,则标记:如果已经访问过,则该索引就为重复的数. 分析: 该算法时间复杂度能够达到最

算法——找出缺失的整数

一.前言 最近智商持续掉线,隐约有种提前犯了阿兹海默症的感觉,偶像剧看多了就是容易智商持续掉线,前一整子关注了个算法的公众号,今天也终于捡着一篇能看懂的了,感觉非常的涨姿势,整篇看下来觉得自己有了很大的提升,仿佛就差一点就看懂了. 以下是原文的链接,为了防止链接被破坏,为了维护涨过的姿势还找得到的和平,阿婆,可爱又迷人的反派角色这里决定开个随笔整理一下文章内容和评论里面的代码,等. 原文请戳这里 http://blog.jobbole.com/106521/ 二.请看正文 第一题:请听题,要把大

【转】已知一个数出现的次数严格超过了一半,请用O(n)的复杂度的算法找出这个数

原文转自:http://blog.csdn.net/zhq651/article/details/7930284 方法1:既然过半,那么用这个数与其他数配对的话,剩余的数字一定还是过半的这个数字.因此可以通过不断删除不同的2个数,直到没有不同的2个数,那么这个数就是要找的数.证明:最坏情况下,只有这个数同别的数配对,并且被删除,剩下的仍旧是这个数,因此得证. 转自:http://www.cnblogs.com/python27/archive/2011/12/15/2289534.html 例:

算法-找出其他出现偶数次的数组中出现1次,2次,3次的数

#include <cstdio> #include <cstring> #include <algorithm> #include <map> #include <iostream> #include<vector> #include<string> #include<set> #include<unordered_set> #include<queue> #include<ma

感知哈希算法&mdash;&mdash;找出相似的图片

Google 图片搜索功能         在谷歌图片搜索中, 用户可以上传一张图片, 谷歌显示因特网中与此图片相同或者相似的图片.         比如我上传一张照片试试效果: 原理讲解         参考Neal Krawetz博士的这篇文章, 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据图片计算出"指纹&qu

感知哈希算法(找出相似的图片)

原理讲解 实现这种功能的关键技术叫做"感知哈希算法"(Perceptual Hash Algorithm), 意思是为图片生成一个指纹(字符串格式), 两张图片的指纹越相似, 说明两张图片就越相似. 但关键是如何根据图片计算出"指纹"呢? 下面用最简单的步骤来说明一下原理: 第一步 缩小图片尺寸 将图片缩小到8x8的尺寸, 总共64个像素. 这一步的作用是去除各种图片尺寸和图片比例的差异, 只保留结构.明暗等基本信息. 第二步 转为灰度图片 将缩小后的图片, 转为6

写一个查找算法找出数组中相同的元素

1 import java.util.ArrayList; 2 3 public class Test { 4 5 // 原始数据data.假设data数组中的数据元素已经按照某种顺序排好. 6 // 但是,该数组中的数据元素重复出现. 7 // 我们的目的是查找.解析data数组中重复出现的某元素. 8 // 比如,在这个data数组中,元素'C'在数组位置2,3重复出现两次. 9 // 注意!有些元素没有重复出现,比如元素'B'. 10 private String[] data = { "

Java实现升序排列的整形数组A,元素两两不相等找出A[i]=i的数据

import java.util.ArrayList; //升序排列的整形数组A,元素两两不相等.请设计高效的算法找出A[i]=i的数据. //使用二种方法 public class BinarySearch { public static void main(String[] args) {     int[] nums={-1,1,2,3};     ArrayList<Integer> res=find(nums);     for(int e:res){      System.out