Array Homework Question

前端 未结 9 1261
庸人自扰
庸人自扰 2020-12-23 16:48

You are given an array with integers between 1 and 1,000,000. One integer is in the array twice. How can you determine which one? Can you think of a way to do it using littl

相关标签:
9条回答
  • 2020-12-23 17:14

    Rather than sorting the array and then checking, I would suggest writing an implementation of a comparison sort function that exits as soon as the dup is found, leading to no extra memory requirement (depending on the algorithm you choose, obviously) and a worst case O(nlogn) time (again, depending on the algorithm), rather than a best (and average, depending...) case O(nlogn) time.

    E.g. An implementation of in-place merge sort.

    http://en.wikipedia.org/wiki/Merge_sort

    0 讨论(0)
  • 2020-12-23 17:18

    This python code is a modification of QuickSort:

    def findDuplicate(arr):
        orig_len = len(arr)
        if orig_len <= 1:
            return None
        pivot = arr.pop(0)
        greater = [i for i in arr if i > pivot]
        lesser = [i for i in arr if i < pivot]
        if len(greater) + len(lesser) != orig_len - 1:
            return pivot
        else:
            return findDuplicate(lesser) or findDuplicate(greater)
    

    It finds a duplicate in O(n logn)), I think. It uses extra memory on the stack, but it can be rewritten to use only one copy of the original data, I believe:

    def findDuplicate(arr):
        orig_len = len(arr)
        if orig_len <= 1:
            return None
        pivot = arr.pop(0)
        greater = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] > pivot]
        lesser = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] < pivot]
        if len(arr):
            return pivot
        else:
            return findDuplicate(lesser) or findDuplicate(greater)
    

    The list comprehensions that produce greater and lesser destroy the original with calls to pop(). If arr is not empty after removing greater and lesser from it, then there must be a duplicate and it must be pivot.

    The code suffers from the usual stack overflow problems on sorted data, so either a random pivot or an iterative solution which queues the data is necessary:

    def findDuplicate(full):
        import copy
        q = [full]
        while len(q):
            arr = copy.copy(q.pop(0))
            orig_len = len(arr)
            if orig_len > 1:
                pivot = arr.pop(0)
                greater = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] > pivot]
                lesser = [arr.pop(i) for i in reversed(range(len(arr))) if arr[i] < pivot]
                if len(arr):
                    return pivot
                else:
                    q.append(greater)
                    q.append(lesser)
        return None
    

    However, now the code needs to take a deep copy of the data at the top of the loop, changing the memory requirements.

    So much for computer science. The naive algorithm clobbers my code in python, probably because of python's sorting algorithm:

    def findDuplicate(arr):
        arr = sorted(arr)
        prev = arr.pop(0)
        for element in arr:
            if element == prev:
                return prev
            else:
                prev = element
        return None
    
    0 讨论(0)
  • 2020-12-23 17:21

    Hint: Use the property that A XOR A == 0, and 0 XOR A == A.

    0 讨论(0)
提交回复
热议问题