您的位置:首页 > 其它

求递增数列中所有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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: