在O(n)中运行的最小缺失整数算法?

时间:2017-02-22 22:22:29

标签: algorithm sorting search

什么算法可能会在数组中找到O(n)时间内丢失的整数?

假设我们有一个数组A,其元素的值范围为{1,2,3 ... 2n}。缺少一半元素,因此A = n的长度。

例如:

A = [1,2,5,3,10],n = 5

输出= 4

2 个答案:

答案 0 :(得分:5)

您可以在O(1)额外空间中执行此操作,假设数组上唯一有效的操作是读取元素和交换元素对。

首先请注意,问题的规范排除了数组包含重复项的可能性:它包含1到2N的一半数字。

我们执行快速选择类型算法。从m = 1开始,M = 2N + 1,并在(m + M)/ 2上旋转数组。如果数组左侧部分的大小(元素< =(m + M)/ 2)小于(m + M)/ 2 - m + 1,那么第一个缺失的数字必须在那里。否则,它必须位于数组的右侧。相应地重复左侧或右侧,直到找到缺失的数字。

每次考虑的阵列切片的大小减半,并且可以在O(n)时间和O(1)空间中旋转大小为n的数组。总的来说,时间复杂度为2N + N + N / 2 + ... + 1 <= 4N = O(N)。

答案 1 :(得分:1)

Paul Hankin在C ++中的想法implementation

#include <iostream>
using namespace std;
const int MAX = 1000;
int a[MAX];
int n;

void swap(int &a, int &b) {
    int tmp = a;
    a = b;
    b = tmp;
}

// Rearranges elements of a[l..r] in such a way that first come elements 
// lower or equal to M, next come elements greater than M. Elements in each group
// come in no particular order.
// Returns an index of the first element among a[l..r] which is greater than M.
int rearrange(int l, int r, int M) {
    int i = l, j = r;
    while (i <= j)
        if (a[i] <= M) i++;
        else swap(a[i], a[j--]);
    return i;
}

int main() {
    cin >> n;
    for (int i = 0; i < n; i++) cin >> a[i];

    int L = 1, R = 2 * n;
    int l = 0, r = n - 1;
    while (L < R) {
        int M = (L + R) / 2; // pivot element
        int m = rearrange(l, r, M); 
        if (m - l == M - L + 1) 
            l = m, L = M + 1;
        else
            r = m - 1, R = M;
    }

    cout << L;
    return 0;
}