在排序数组中查找未重复元素

时间:2013-06-14 21:14:49

标签: arrays algorithm complexity-theory

来源:Microsoft面试问题

给定一个排序数组,其中每个元素出现两次,除了一次出现的单元,我们需要找到该元素。

现在标准的O(n)解决方案是执行列表的异或,它将返回未重复的元素(因为所有重复的元素都会被取消。)

如果我们知道数组已经排序,是否有可能更快地解决这个问题?

3 个答案:

答案 0 :(得分:14)

是的,你可以使用排序来通过二进制搜索将复杂性降低到O(log n)

由于数组已经排序,在缺失元素之前,每个值占据数组中的点2*k2*k+1(假设基于0的索引)。

所以你转到数组的中间,比如索引h,如果h+1是偶数,则检查索引h,如果h-1,则检查h是奇怪的。如果缺少的元素稍后出现,则这些位置的值相等,如果之前的值,则值不同。重复,直到找到缺失的元素。

答案 1 :(得分:6)

对数组执行二进制“搜索”(而不是遍历),检查两个邻居,如果两者都不同于中间的值,则可以使用解决方案。这是O(log n)

答案 2 :(得分:1)

是的,数组已排序,因此我们可以应用二进制搜索来查找单个元素。让我们看看单个元素的发生模式。元素总数始终为奇数,单个元素仅在偶数索引处出现

Total number of elements 9, single elements always present at even index

元素总数9,单个元素始终以偶数索引出现。 当(end_index - start_index) % 4 == 0时,单个元素出现在中间。

if A[mid-1] == A[mid] --> single element left side
if A[mid] == A[mid+1] --> single element right side

Total number of elements 11

元素总数11,单个元素始终以偶数索引出现。当(end_index - start_index) % 4 != 0时,单个元素不在中间。

if A[mid] == A[mid+1] --> single element left
if A[mid-1] == A[mid] --> single element right

enter image description here

元素总数13,单个元素始终以偶数索引出现。当(end_index - start_index) % 4 == 0时,单个元素也在中间出现。

if A[mid-1] == A[mid] --> single element left side
if A[mid] == A[mid+1] --> single element right side

下面是Python代码:

class Solution:
    def singleNonDuplicate(self, A):
        """
        :type nums: List[int]
        :rtype: int
        """
        L = len(A)

        def binarySearch(A, start, end):
            if start == end:
                return A[start]

            if start < end:

                mid = int(start + (end - start)/2)

                if A[mid-1] < A[mid] < A[mid+1]:
                    return A[mid]
                if end - start == 2:
                    if A[end] != A[end-1]:
                        return A[end]
                if end - start == 2:
                    if A[start] != A[start+1]:
                        return A[start]
                if A[mid] == A[mid+1]:
                    if int(end-start)%4 == 0:
                        return binarySearch(A, mid+2, end)
                    else:
                        return binarySearch(A, start, mid-1)

                elif A[mid-1] == A[mid]:
                    if int(end - start)%4 == 0:
                        return binarySearch(A, start, mid-2)
                    else:
                        return binarySearch(A, mid+1, end)

        return binarySearch(A, 0, L-1)


if __name__ == "__main__":

    s = Solution()
    A = [1,1,2,3,3,4,4,5,5,6,6]
    r = s.singleNonDuplicate(A)
    print(r)