development

목록에없는 가장 작은 정수 찾기

big-blog 2020. 9. 17. 08:24
반응형

목록에없는 가장 작은 정수 찾기


제 동료가 사용하는 흥미로운 인터뷰 질문 :

부호없는 64 비트 정수의 매우 길고 정렬되지 않은 목록이 제공되었다고 가정하십시오. 목록에 없는 가장 작은 음이 아닌 정수를 어떻게 찾을 수 있습니까?

FOLLOW-UP : 분류에 의한 명백한 해결책이 제안되었으므로 O (n log n)보다 빠르게 할 수 있습니까?

후속 조치 : 알고리즘은 1GB의 메모리가있는 컴퓨터에서 실행되어야합니다.

설명 : 목록은 RAM에 있지만 많은 양을 소비 할 수 있습니다. 목록의 크기 (예 : N)가 미리 제공됩니다.


데이터 구조가 제자리에서 변경 될 수 있고 임의 액세스를 지원하는 경우 O (N) 시간 및 O (1) 추가 공간에서 수행 할 수 있습니다. 배열을 순차적으로 살펴보고 모든 인덱스에 대해 인덱스의 값을 값으로 지정된 인덱스에 쓰고 해당 위치의 값을 해당 위치에 재귀 적으로 배치하고 값> N을 버립니다. 그런 다음 다시 배열을 통해 스팟을 찾습니다. 값이 인덱스와 일치하지 않는 경우-배열에없는 가장 작은 값입니다. 이로 인해 최대 3N 비교가 수행되고 임시 공간에 해당하는 몇 가지 값만 사용됩니다.

# Pass 1, move every value to the position of its value
for cursor in range(N):
    target = array[cursor]
    while target < N and target != array[target]:
        new_target = array[target]
        array[target] = target
        target = new_target

# Pass 2, find first location where the index doesn't match the value
for cursor in range(N):
    if array[cursor] != cursor:
        return cursor
return N

다음 O(N)O(N)공간 을 사용 하는 간단한 솔루션입니다 . 입력 목록을 음수가 아닌 숫자로 제한하고 목록에없는 첫 번째 음이 아닌 숫자를 찾고 싶다고 가정합니다.

  1. 목록의 길이를 찾으십시오. 그것은이라고 말할 수 있습니다 N.
  2. Nall로 초기화 된 부울 배열을 할당 합니다 false.
  3. X목록의 각 숫자 에 대해 X보다 작은 경우 배열 NX'th요소를로 설정합니다 true.
  4. index 0에서 시작하는 배열을 스캔하여 인 첫 번째 요소를 찾습니다 false. 첫 번째 발견하면 false인덱스를 I, 다음 I답변입니다. 그렇지 않으면 (즉, 모든 요소가있을 때 true) 대답은 N입니다.

실제로 " N부울 배열 "은 byte또는 int배열 로 표시되는 "비트 맵"또는 "비트 세트"로 인코딩 될 수 있습니다 . 이것은 일반적으로 더 적은 공간 (프로그래밍 언어에 따라 다름)을 사용하고 첫 번째 스캔이 false더 빨리 수행되도록합니다.


이것이 알고리즘이 작동하는 방법 / 이유입니다.

N목록 숫자가 구별되지 않거나 그 중 하나 이상이보다 크다고 가정 N합니다. 이 수단이 있어야한다는 최소한 의 범위에서 하나 개의 번호 0 .. N - 1목록에 없습니다. 따라서 가장 작은 결측 수를 찾는 문제는 따라서 보다N 작은 결측 수를 찾는 문제로 축소되어야합니다 . 이것은 N... 보다 크거나 같은 숫자를 추적 할 필요가 없다는 것을 의미합니다 . 왜냐하면 그들은 답이 될 수 없기 때문입니다.

이전 단락의 대안은 목록이에서 번호의 순열이라는 것입니다 0 .. N - 1. 이 경우 3 단계에서는 배열의 모든 요소를로 설정하고 true4 단계에서는 첫 번째 "누락 된"숫자가 N입니다.


알고리즘의 계산 복잡도 O(N)는 상대적으로 작은 비례 상수입니다. 목록을 두 번의 선형 통과 또는 목록 길이가 시작하는 것으로 알려진 경우 한 번만 통과합니다. 전체 목록을 메모리에 저장할 필요가 없습니다. 따라서 알고리즘의 점근 적 메모리 사용량은 부울 배열을 나타내는 데 필요한 것입니다. O(N)비트.

(반대로, 메모리 내 정렬 또는 파티셔닝에 의존하는 알고리즘은 전체 목록을 메모리에 나타낼 수 있다고 가정합니다. 질문 형식에서는 O(N)64 비트 단어 가 필요합니다 .)


1 ~ 3 단계의 @Jorn 주석은 계산 정렬의 변형입니다. 어떤 의미에서 그는 옳지 만 차이점은 중요합니다.

  • 계수 정렬에는 목록에서 가장 큰 숫자이고 목록 에서 가장 작은 숫자 인 (적어도) Xmax - Xmin카운터 배열이 필요 합니다. 각 카운터는 N 상태를 나타낼 수 있어야합니다. 즉, 이진 표현을 가정하면 정수 유형 (적어도) 비트 가 있어야 합니다.XmaxXminceiling(log2(N))
  • 배열 크기를 결정하려면 계수 정렬을 통해 목록을 처음 통과하여 Xmax을 결정해야합니다 Xmin.
  • 따라서 최소 최악의 경우 공간 요구 사항은 ceiling(log2(N)) * (Xmax - Xmin)비트입니다.

대조적으로, 위에 제시된 알고리즘은 단순히 N최악의 경우와 최상의 경우의 비트를 필요로합니다 .

그러나이 분석은 알고리즘이 목록을 처음 통과하여 0을 찾고 (필요한 경우 목록 요소를 세는 경우) 0을 찾은 경우 공백을 사용하지 않고 더 빠른 답변을 제공한다는 직관으로 이어집니다. 목록에서 하나 이상의 0을 찾을 가능성이 높은 경우이 작업을 수행 할 가치가 있습니다. 그리고이 추가 패스는 전반적인 복잡성을 변경하지 않습니다.


편집 : 사람들이 비트와 비트 맵을 사용하는 내 원래 설명이 혼란스러워 보이기 때문에 "부울 배열"을 사용하도록 알고리즘 설명을 변경했습니다.


OP는 이제 원래 목록이 RAM에 있고 컴퓨터에 1GB의 메모리 만 있다고 지정 했으므로 팔다리로 나가서 대답이 0이라고 예측합니다.

1GB RAM은 목록에 최대 134,217,728 개의 숫자를 포함 할 수 있음을 의미합니다. 그러나 2 64 = 18,446,744,073,709,551,616 개의 가능한 숫자가 있습니다. 따라서 목록에 0이있을 확률은 137,438,953,472 중 1입니다.

대조적으로, 올해 번개맞을 확률은 70 만분의 1입니다. 운석에 맞을 확률 은 약 10 조분의 1입니다. 그래서 저는 답이 0이 아닌 것보다 천체에 의해 제때에 죽지 않아서 과학 저널에 기록 될 가능성이 약 10 배 더 높습니다.


다른 답변에서 지적했듯이 정렬을 수행 한 다음 간격을 찾을 때까지 간단히 스캔 할 수 있습니다.

알고리즘 복잡성을 O (N)으로 개선하고 간격을 포함 할 수있는 잠재적 후보가 아닌 파티션을 제거하는 수정 된 QuickSort를 사용하여 O (N) 공간을 유지할 수 있습니다.

  • 첫 번째 파티션 단계에서 중복을 제거합니다.
  • 파티셔닝이 완료되면 하위 파티션의 항목 수를 확인하십시오.
  • 이 값이 파티션 생성에 사용 된 값과 같습니까?
    • 그렇다면 더 높은 파티션에 간격이 있음을 의미합니다.
      • 하위 파티션을 무시하고 빠른 정렬을 계속합니다.
    • 그렇지 않으면 간격이 아래쪽 파티션에 있습니다.
      • 더 높은 파티션을 무시하고 빠른 정렬을 계속합니다.

이것은 많은 계산을 저장합니다.


숫자는 모두 64 비트이므로 기수 정렬 (O (n))을 사용할 수 있습니다 . 정렬 한 다음 원하는 것을 찾을 때까지 스캔하십시오.

가장 작은 숫자가 0이면 간격을 찾을 때까지 앞으로 스캔합니다. 가장 작은 숫자가 0이 아니면 답은 0입니다.


O(N)사고 의 함정 중 하나를 설명하기 위해 여기 공간 O(N)을 사용 하는 알고리즘이 O(1)있습니다.

for i in [0..2^64):
  if i not in list: return i

print "no 64-bit integers are missing"

공간 효율적인 방법과 모든 값이 구별되는 경우 공간 O( k )과 시간 에서 수행 할 수 있습니다 O( k*log(N)*N ). 공간 효율적이고 데이터 이동이 없으며 모든 작업이 기본 (더하기 빼기)입니다.

  1. 세트 U = N; L=0
  2. 먼저 k영역 의 숫자 공간을 분할합니다 . 이렇게 :
    • 0->(1/k)*(U-L) + L, 0->(2/k)*(U-L) + L, 0->(3/k)*(U-L) + L...0->(U-L) + L
  3. count{i}각 지역에 몇 개의 숫자 ( )가 있는지 확인합니다 . ( N*k단계)
  4. h가득 차지 않은 첫 번째 지역 ( )을 찾습니다 . 그것은 의미 count{h} < upper_limit{h}합니다. ( k단계)
  5. h - count{h-1} = 1답이 있다면
  6. 세트 U = count{h}; L = count{h-1}
  7. 2로 이동

이것은 해싱을 사용하여 개선 될 수 있습니다 (Nic이 아이디어에 감사드립니다).

  1. 같은
  2. 먼저 k영역 의 숫자 공간을 분할합니다 . 이렇게 :
    • L + (i/k)->L + (i+1/k)*(U-L)
  3. inc count{j} 사용 j = (number - L)/k (if L < number < U)
  4. hk 요소가없는 첫 번째 영역 ( ) 찾기
  5. count{h} = 1h가 당신의 대답 이라면
  6. 세트 U = maximum value in region h L = minimum value in region h

이것은에서 실행됩니다 O(log(N)*N).


나는 그것들을 정렬 한 다음 간격 (0과 첫 번째 숫자 사이의 간격 포함)을 찾을 때까지 시퀀스를 실행합니다.

알고리즘 측면에서 다음과 같이 할 수 있습니다.

def smallest_not_in_list(list):
    sort(list)
    if list[0] != 0:
        return 0
    for i = 1 to list.last:
        if list[i] != list[i-1] + 1:
            return list[i-1] + 1
    if list[list.last] == 2^64 - 1:
        assert ("No gaps")
    return list[list.last] + 1

물론 CPU grunt보다 더 많은 메모리가 있다면 가능한 모든 64 비트 값의 비트 마스크를 만들고 목록의 모든 숫자에 대해 비트를 설정할 수 있습니다. 그런 다음 해당 비트 마스크에서 첫 번째 0 비트를 찾습니다. 그것은 시간 측면에서 O (n) 작업으로 바뀌지 만 메모리 요구 사항 측면에서는 상당히 비쌉니다. :-)

나는 당신이 O (n)을 향상시킬 수 있을지 의심 스럽습니다. 적어도 한 번은 각 숫자를 보지 않는 방법을 볼 수 없기 때문입니다.

그 알고리즘은 다음과 같습니다.

def smallest_not_in_list(list):
    bitmask = mask_make(2^64) // might take a while :-)
    mask_clear_all (bitmask)
    for i = 1 to list.last:
        mask_set (bitmask, list[i])
    for i = 0 to 2^64 - 1:
        if mask_is_clear (bitmask, i):
            return i
    assert ("No gaps")

목록을 정렬하고 첫 번째와 두 번째 요소를 살펴본 다음 간격이 생길 때까지 위로 올라가십시오.


숨겨진 요소는 상당히 크지 만 O (n) 시간과 O (1) 추가 공간에서 할 수 있습니다. 이것은 문제를 해결하는 실용적인 방법은 아니지만 그럼에도 불구하고 흥미로울 수 있습니다.

모든 부호없는 64 비트 정수 (오름차순)에 대해 대상 정수를 찾거나 목록 끝에 도달 할 때까지 목록을 반복합니다. 목록 끝에 도달하면 대상 정수는 목록에없는 가장 작은 정수입니다. 64 비트 정수의 끝에 도달하면 모든 64 비트 정수가 목록에 있습니다.

다음은 Python 함수입니다.

def smallest_missing_uint64(source_list):
    the_answer = None

    target = 0L
    while target < 2L**64:

        target_found = False
        for item in source_list:
            if item == target:
                target_found = True

        if not target_found and the_answer is None:
            the_answer = target

        target += 1L

    return the_answer

이 함수는 O (n)을 유지하기 위해 의도적으로 비효율적입니다. 특히이 함수는 답을 찾은 후에도 대상 정수를 계속 확인합니다. 답이 발견 되 자마자 함수가 반환되면 외부 루프가 실행 된 횟수는 n으로 묶인 답의 크기에 의해 제한됩니다. 그 변경은 비록 훨씬 더 빠르더라도 실행 시간을 O (n ^ 2)로 만들 것입니다.


영감을 주신 egon, swilden 및 Stephen C에게 감사드립니다. 첫째, 목표 값이 목록의 크기보다 클 수 없기 때문에 목표 값의 경계를 알고 있습니다. 또한 1GB 목록에는 최대 134217728 (128 * 2 ^ 20) 64 비트 정수가 포함될 수 있습니다.

해싱 부분
나는 검색 공간을 극적으로 줄이기 위해 해싱을 사용하는 것을 제안합니다. 먼저 목록 크기의 제곱근입니다. 1GB 목록의 경우 N = 11,586입니다. 크기 N의 정수 배열을 설정합니다. 목록을 반복하고 찾은 각 숫자의 제곱근 *을 해시로 사용합니다. 해시 테이블에서 해당 해시에 대한 카운터를 증가시킵니다. 다음으로 해시 테이블을 반복합니다. 최대 크기와 같지 않은 첫 번째 버킷이 새 검색 공간을 정의합니다.

비트 맵 부분
이제 새 검색 공간의 크기와 동일한 일반 비트 맵을 설정하고 다시 소스 목록을 반복하여 검색 공간에서 각 숫자를 찾을 때 비트 맵을 채우십시오. 완료되면 비트 맵의 ​​첫 번째 설정되지 않은 비트가 답을 제공합니다.

이것은 O (n) 시간과 O (sqrt (n)) 공간에서 완료됩니다.

(* 비트 시프 팅과 같은 것을 사용하여이 작업을 훨씬 더 효율적으로 수행하고 그에 따라 버킷의 수와 크기를 변경할 수 있습니다.)


숫자 목록에 누락 된 숫자가 하나만있는 경우 누락 된 숫자를 찾는 가장 쉬운 방법은 계열을 더하고 목록의 각 값을 빼는 것입니다. 최종 값은 누락 된 숫자입니다.


 int i = 0;
            while ( i < Array.Length)
            {

                if (Array[i] == i + 1)
                {
                    i++;
                }

                if (i < Array.Length)
                {
                    if (Array[i] <= Array.Length)
                    {//SWap

                        int temp = Array[i];
                        int AnoTemp = Array[temp - 1];
                        Array[temp - 1] = temp;
                        Array[i] = AnoTemp;

                    }
                    else
                       i++;



                }
            }

            for (int j = 0; j < Array.Length; j++)
            {
                if (Array[j] > Array.Length)
                {
                    Console.WriteLine(j + 1);
                    j = Array.Length;
                }
                else
                    if (j == Array.Length - 1)
                        Console.WriteLine("Not Found !!");

            }
        }

해시 테이블을 사용하여 숫자를 저장할 수 있습니다. 모든 숫자가 완료되면 0부터 가장 낮은 숫자를 찾을 때까지 카운터를 실행합니다. 합리적으로 좋은 해시는 일정한 시간에 해시 및 저장하고 일정한 시간에 검색합니다.

for every i in X         // One scan Θ(1)
   hashtable.put(i, i);  // O(1)

low = 0;

while (hashtable.get(i) <> null)   // at most n+1 times
   low++;

print low;

n배열에 요소가있는 경우 최악의 경우 이며 {0, 1, ... n-1},이 경우 대답은에서 얻을 수 있으며 n여전히 유지합니다 O(n).


Java로 작성된 내 대답은 다음과 같습니다.

기본 아이디어 : 1- 중복 된 양수, 0 및 음수를 버리고 나머지를 합산하고 최대 양수도 얻고 맵에서 고유 한 양수를 유지하면서 배열을 반복합니다.

2- 합을 max * (max + 1) / 2로 계산합니다.

3- 1 단계와 2 단계에서 계산 된 합계의 차이 찾기

4- 1에서 [sums difference, max]의 최소값까지 다시 반복하고 1 단계에서 채운지도에없는 첫 번째 숫자를 반환합니다.

public static int solution(int[] A) {
    if (A == null || A.length == 0) {
        throw new IllegalArgumentException();
    }

    int sum = 0;
    Map<Integer, Boolean> uniqueNumbers = new HashMap<Integer, Boolean>();
    int max = A[0];
    for (int i = 0; i < A.length; i++) {
        if(A[i] < 0) {
            continue;
        }
        if(uniqueNumbers.get(A[i]) != null) {
            continue;
        }
        if (A[i] > max) {
            max = A[i];
        }
        uniqueNumbers.put(A[i], true);
        sum += A[i];
    }
    int completeSum = (max * (max + 1)) /  2;
    for(int j = 1; j <= Math.min((completeSum - sum), max); j++) {
        if(uniqueNumbers.get(j) == null) { //O(1)
            return j;
        }
    }
    //All negative case
    if(uniqueNumbers.isEmpty()) {
        return 1;
    }
    return 0;
}

Stephen C가 현명하게 지적했듯이 대답은 배열 길이보다 작은 숫자 여야합니다. 그런 다음 이진 검색으로 답을 찾을 수 있습니다. 이것은 최악의 경우를 최적화합니다 (그래서 면접관은 '가정'병리 적 시나리오에서 당신을 잡을 수 없습니다). 인터뷰에서 최악의 경우에 최적화하기 위해이 작업을 수행하고 있음을 지적하십시오.

이진 검색을 사용하는 방법은 배열의 각 요소에서 찾고있는 숫자를 빼고 부정적인 결과를 확인하는 것입니다.


나는 "제로 추측"장치를 좋아한다. 숫자가 무작위이면 0 일 가능성이 높습니다. "시험관"이 무작위가 아닌 목록을 설정 한 경우 하나를 추가하고 다시 추측하십시오.

LowNum=0
i=0
do forever {
  if i == N then leave /* Processed entire array */
  if array[i] == LowNum {
     LowNum++
     i=0
     }
   else {
     i++
   }
}
display LowNum

최악의 경우는 n = N 인 n * N이지만 실제로 n은 작은 숫자 일 가능성이 높습니다 (예 : 1).


질문이 있는지 확실하지 않습니다. 그러나 목록 1,2,3,5,6의 경우 누락 된 숫자가 4이면 누락 된 숫자는 O (n)에서 다음과 같이 찾을 수 있습니다. (n + 2) (n + 1) / 2- (n + 1) n / 2

편집 : 미안 해요, 어젯밤에 너무 빨리 생각하고 있었던 것 같아요. 어쨌든 두 번째 부분은 실제로 O (n)이 오는 sum (list)로 대체되어야합니다. 공식은 그이면에있는 아이디어를 보여줍니다. n 개의 연속 정수의 경우 합계는 (n + 1) * n / 2 여야합니다. 누락 된 숫자가있는 경우 합계는 (n + 1) 순차 정수의 합계에서 누락 된 숫자를 뺀 값과 같습니다.

마음 속에 중간 부분을 넣었다는 사실을 지적 해주셔서 감사합니다.


잘 했어요 Ants Aasma! 나는 약 15 분 동안 그 답에 대해 생각했고, 당신과 비슷한 생각의 맥락에서 독립적으로 답을 내놓았습니다.

#define SWAP(x,y) { numerictype_t tmp = x; x = y; y = tmp; }
int minNonNegativeNotInArr (numerictype_t * a, size_t n) {
    int m = n;
    for (int i = 0; i < m;) {
        if (a[i] >= m || a[i] < i || a[i] == a[a[i]]) {
            m--;
            SWAP (a[i], a[m]);
            continue;
        }
        if (a[i] > i) {
            SWAP (a[i], a[a[i]]);
            continue;
        }
        i++;
    }
    return m;
}

m은 "처음 i 입력에 대해 알고 있고 m-1에 입력 할 때까지 값에 대해 아무것도 가정하지 않은 경우 현재 가능한 최대 출력"을 나타냅니다.

이 m 값은 (a [i], ..., a [m-1])이 값 (i, ..., m-1)의 순열 인 경우에만 반환됩니다. 따라서 a [i]> = m 또는 a [i] <i 또는 a [i] == a [a [i]] 인 경우 m이 잘못된 출력이고 적어도 하나의 요소가 낮아야 함을 압니다. 따라서 m을 줄이고 a [i]를 a [m]으로 바꾸면 재귀 할 수 있습니다.

이것이 사실이 아니라 a [i]> i 인 경우 a [i]! = a [a [i]] a [i]를 a [a [i]]로 바꾸면 요소 수가 증가한다는 것을 알고 있습니다. 자신의 자리에서.

그렇지 않으면 a [i]는 i와 같아야합니다.이 경우이 인덱스까지 포함하는 모든 값이 인덱스와 같다는 것을 알고 i를 증가시킬 수 있습니다.

이것이 무한 루프에 들어갈 수 없다는 증거는 독자에게 연습으로 남겨집니다. :)


Dafny의 개미 '대답 쇼에서 조각은 왜 제자리 알고리즘이 실패 할 수 있습니다. requires전제 조건은 각 항목의 값이 배열의 범위를 넘어서는 안된다는 것을 설명합니다.

method AntsAasma(A: array<int>) returns (M: int)
  requires A != null && forall N :: 0 <= N < A.Length ==> 0 <= A[N] < A.Length;
  modifies A; 
{
  // Pass 1, move every value to the position of its value
  var N := A.Length;
  var cursor := 0;
  while (cursor < N)
  {
    var target := A[cursor];
    while (0 <= target < N && target != A[target])
    {
        var new_target := A[target];
        A[target] := target;
        target := new_target;
    }
    cursor := cursor + 1;
  }

  // Pass 2, find first location where the index doesn't match the value
  cursor := 0;
  while (cursor < N)
  {
    if (A[cursor] != cursor)
    {
      return cursor;
    }
    cursor := cursor + 1;
  }
  return N;
}

forall ...확인 오류를 보려면 절이 있거나없는 코드를 유효성 검사기에 붙여 넣습니다 . 두 번째 오류는 검증자가 패스 1 루프에 대한 종료 조건을 설정할 수없는 결과입니다. 이를 증명하는 것은 도구를 더 잘 이해하는 사람에게 맡겨집니다.


다음은 입력을 수정하지 않고 O (N) 시간 및 N 비트와 작은 상수 메모리 오버 헤드 (여기서 N은 목록의 크기)를 사용하는 Java의 답변입니다.

int smallestMissingValue(List<Integer> values) {
    BitSet bitset = new BitSet(values.size() + 1);
    for (int i : values) {
        if (i >= 0 && i <= values.size()) {
            bitset.set(i);
        }
    }
    return bitset.nextClearBit(0);
}

def solution(A):

index = 0
target = []
A = [x for x in A if x >=0]

if len(A) ==0:
    return 1

maxi = max(A)
if maxi <= len(A):
    maxi = len(A)

target = ['X' for x in range(maxi+1)]
for number in A:
    target[number]= number

count = 1
while count < maxi+1:
    if target[count] == 'X':
        return count
    count +=1
return target[count-1] + 1

위의 솔루션에 대해 100 %를 얻었습니다.


1) 네거티브 및 제로 필터링

2) 정렬 / 구별

3) 방문 배열

복잡성 : O (N) 또는 O (N * log (N))

Java8 사용

public int solution(int[] A) {
            int result = 1;
    boolean found = false;
    A = Arrays.stream(A).filter(x -> x > 0).sorted().distinct().toArray();
    //System.out.println(Arrays.toString(A));
    for (int i = 0; i < A.length; i++) {
        result = i + 1;
        if (result != A[i]) {
            found = true;
            break;
        }
    }
    if (!found && result == A.length) {
        //result is larger than max element in array
        result++;
    }
    return result;
}

순서가 지정되지 않은 집합은 모든 양수를 저장하는 데 사용될 수 있습니다. 그런 다음 1에서 순서없는 집합의 길이까지 반복하여 발생하지 않는 첫 번째 숫자를 볼 수 있습니다.

int firstMissingPositive(vector<int>& nums) {

    unordered_set<int> fre;
    // storing each positive number in a hash.
    for(int i = 0; i < nums.size(); i +=1)
    {
        if(nums[i] > 0)
            fre.insert(nums[i]);
     }

    int i = 1;
    // Iterating from 1 to size of the set and checking 
    // for the occurrence of 'i'

    for(auto it = fre.begin(); it != fre.end(); ++it)
    {
        if(fre.find(i) == fre.end())
            return i;
        i +=1;
    }

    return i;
}

기본 자바 스크립트를 통한 솔루션

var a = [1, 3, 6, 4, 1, 2];

function findSmallest(a) {
var m = 0;
  for(i=1;i<=a.length;i++) {
    j=0;m=1;
    while(j < a.length) {
      if(i === a[j]) {
        m++;
      }
      j++;
    }
    if(m === 1) {
      return i;
    }
  }
}

console.log(findSmallest(a))

이것이 누군가에게 도움이되기를 바랍니다.


파이썬을 사용하면 가장 효율적이지는 않지만 정확합니다.

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import datetime

# write your code in Python 3.6

def solution(A):
    MIN = 0
    MAX = 1000000
    possible_results = range(MIN, MAX)

    for i in possible_results:
        next_value = (i + 1)
        if next_value not in A:
            return next_value
    return 1

test_case_0 = [2, 2, 2]
test_case_1 = [1, 3, 44, 55, 6, 0, 3, 8]
test_case_2 = [-1, -22]
test_case_3 = [x for x in range(-10000, 10000)]
test_case_4 = [x for x in range(0, 100)] + [x for x in range(102, 200)]
test_case_5 = [4, 5, 6]
print("---")
a = datetime.datetime.now()
print(solution(test_case_0))
print(solution(test_case_1))
print(solution(test_case_2))
print(solution(test_case_3))
print(solution(test_case_4))
print(solution(test_case_5))

def solution(A):
    A.sort()
    j = 1
    for i, elem in enumerate(A):
        if j < elem:
            break
        elif j == elem:
            j += 1
            continue
        else:
            continue
    return j

이것은 도움이 될 수 있습니다 :

0- A is [5, 3, 2, 7];
1- Define B With Length = A.Length;                            (O(1))
2- initialize B Cells With 1;                                  (O(n))
3- For Each Item In A:
        if (B.Length <= item) then B[Item] = -1                (O(n))
4- The answer is smallest index in B such that B[index] != -1  (O(n))

참고 URL : https://stackoverflow.com/questions/1586858/find-the-smallest-integer-not-in-a-list

반응형