求递增数列中所有A[i]=i的元素(阿里巴巴2013笔试题)
2016-02-18 12:26
239 查看
求递增数列中所有A[i]=i的元素
阅读更多博客,请访问博主的个人网站 点击访问网站题意描述
给定一个排好升序的数组A[1]、A[2]、……、A,其元素两两不相等。请设计一高效的算法找出中间所有A[i] = i的下标。并分析其复杂度。
思路分析
该题目有两个重要的条件:1. 排好升序的数组
2. 元素两两不相等
我们根据以上两个已知条件可以得出以下定理:
定理1:在递增序列中A中,对于A的所有元素A[i],如果满足A[i] = i, 则他们组成一个连续的序列。
对于定理1这里不作证明,只给出两个例子来阐述定理的意义。
1. 已知A中满足条件的元素只有A[i],A[j],A[k]三个,且i < j < k,那么我们根据定理1就可以断言:i + 1 = j 且 j + 1 = k。
2. 已知A中有元素A[i] = i, A[i + 1] = i + 1,但是A[i + 2] ≠ i + 2,那么A[i + 2]后面的元素也不会再有满足条件的元素了。同理,若A[i - 1] ≠i - 1,那么可以推出A[i - 1]前面也不会再有满足条件的元素了。
算法设计
由定理1知,所有满足条件的元素挨在一块组成一个连续数列。我们的算法就是找出这个数列的左边界和右边界。1. 二分查找左边界,即满足 A[i] = i 且 A[i - 1] < i - 1的位置。
2. 二分查找右边界,即满足A[i] = i 且A[i + 1] > i + 1。
3. 左边界到右边界之间的即为满足条件的元素。
代码实现(python)
class Solution: def getLeftBound(self, a): low = 0 high = len(a) - 1 while low <= high: mid = (low + high) / 2 if a[mid] == mid and (mid == 0 or a[mid - 1] != mid - 1): return mid elif a[mid] < mid: low = mid + 1 elif a[mid] > mid: high = mid - 1 else: high = mid - 1 return -1 def getRightBound(self, a): low = 0 high = len(a) - 1 while low <= high: mid = (low + high) / 2 if a[mid] == mid and (mid == len(a) - 1 or a[mid + 1] != mid + 1): return mid elif a[mid] < mid: low = mid + 1 elif a[mid] > mid: high = mid - 1 else: low = mid + 1 return -1 def getAns(self, a): l = self.getLeftBound(a) r = self.getRightBound(a) return a[l : r + 1] s = Solution() a = [-1, 0, 2, 3, 4, 5, 6, 9] print s.getAns(a)
复杂度分析(时间)
代码中getLeftBound()和getRightBound()都是二分查找的过程,复杂度为O(logn)最后返回满足条件的元素 的操作,复杂度为O(n)
相关文章推荐
- js详解之作用域-实例
- Xcode7 配置pch文件
- Hive索引
- HDU 5627 Clarke and MST
- Pod在墙内
- 关于C#中的抽象类、抽象方法和虚方法的探究
- 现在的问题
- [置顶] 让Linux系统启动过程自动运行自己编写的脚本
- centos 下 69 column window is too narrow
- Mysql表使用全文索引
- work_note 2016年2月18日, PM 12:21:29
- SVN常用命令
- poj1014 dfs/背包/类筛法求素数
- 剑指Offer:包含min函数的栈(JAVA)
- 【SPOJ-BTTNS】Buttons【高斯消元】【异或方程组】
- [iOS]The app icon set named "AppIcon" did not have any applicable content
- __stdcall,__cdecl,__fastcall的区别
- 初窥Linux 之 我最常用的20条命令
- 人物动画的控制
- HDU 5626 Clarke and points