簡體   English   中英

返回 Array 中未出現的最小正 integer(大於 0)

[英]returns the smallest positive integer (greater than 0) that does not occur in Array

我有以下問題:-

寫一個 function:

class Solution { public int solution(int[] A); }

即,給定一個包含 N 個整數的數組 A,返回 A 中未出現的最小正 integer(大於 0)。

例如,給定 A = [1, 3, 6, 4, 1, 2],function 應該返回 5。

給定 A = [1, 2, 3],function 應該返回 4。

給定 A = [−1, −3],function 應返回 1。

為以下假設編寫一個有效的算法:

  • N 是 [1..100,000] 范圍內的 integer;
  • 數組 A 的每個元素都是 [−1,000,000..1,000,000] 范圍內的 integer。

現在我嘗試了這段代碼:-

using System;
// you can also use other imports, for example:
// using System.Collections.Generic;

// you can write to stdout for debugging purposes, e.g.
// Console.WriteLine("this is a debug message");

class Solution
{
    public int solution(int[] A)
    {
        // write your code in C# 6.0 with .NET 4.5 (Mono)
        int n = 1;
        Array.Sort(A);
        for (int i = 1; i <= 100000; i++)
        {
            for (int i2 = 0; i2 <= A.Length - 1; i2++)
            {
                if (A[i2] == i)

                {
                    n = A[i2] + 1;
                    break;
                }

            }



        }
        return n;

    }
}

我的代碼對這些測試數據運行良好:-

A = [1, 2, 3]

A = [-1, -3]

雖然這個失敗了:-

A = [1, 3, 6, 4, 1, 2] 返回 7 而不是 5。

有什么建議為什么我的代碼在第三次測試中失敗了?

謝謝

using System.Linq;

int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();

我將使用以下方法,使用HashSet<int>檢查給定的 integer 是否丟失:

public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
     HashSet<int> hs = new HashSet<int>(A);
     for (int i = rangeStart; i <= rangeEnd; i++)
        if(!hs.Contains(i)) return i;
     
     return null;
}

HashSet是唯一值的集合,並且在查找項目時非常有效(復雜度為O(1) )。 因此,您以一些 memory 為代價獲得了一個非常易讀且高效的算法。

也許你可以通過提供另一種算法來優化它,以防數組非常大,你不想冒險OutOfMemoryException

public static int? SmallestMissing(int[] A, int rangeStart = 1, int rangeEnd = 100_000)
{
    if(A.Length > 1_000_000)
    {
        Array.Sort(A);
        for (int i = rangeStart; i <= rangeEnd; i++)
        {
            int index = Array.BinarySearch(A, i);
            if(index < 0) return i;
        }
        return null;
    }
    
    HashSet<int> hs = new HashSet<int>(A);
    for (int i = rangeStart; i <= rangeEnd; i++)
        if(!hs.Contains(i)) return i;
 
    return null;
} 

如果您被允許對數組進行就地排序,這意味着修改輸入參數值,這里有一個簡單的缺失值線性探測(當然是在排序的頂部)。

這是偽代碼:

Sort the array
Skip all negatives and 0's at the start
Loopify the following:
    Expect 1, if not found at current location return 1
    Skip all 1's
    Expect 2, if not found at current location return 2
    Skip all 2's
    Expect 3, if not found at current location return 3
    Skip all 3's
    ... and so on for 4, 5, 6, etc. until end of array
If we get here, return currently expected value which should've been at the end

這是代碼:

public static int FirstMissingValue(int[] input)
{
    Array.Sort(input);
    
    int index = 0;
    
    // Skip negatives
    while (index < input.Length && input[index] < 1)
        index++;

    int expected = 1;
    while (index < input.Length)
    {
        if (input[index] > expected)
            return expected;
            
        // Skip number and all duplicates
        while (index < input.Length && input[index] == expected)
            index++;
            
        expected++;
    }
    
    return expected;
}

測試用例:

Console.WriteLine(FirstMissingValue(new[] { 1, 3, 6, 4, 1, 2 }));
Console.WriteLine(FirstMissingValue(new[] { 1, 2, 3 }));
Console.WriteLine(FirstMissingValue(new[] { -1, -3 }));

output:

5
4
1

如果輸入數組變成這樣,您的 alg 將不起作用:[1,2-1,1,3,5]。 我是根據你的算法做的。 試試看:

int[] a = new int[] { -1, -2};

        IEnumerable<int> uniqueItems = a.Distinct<int>().Where(x => x > 0);
        
        if (uniqueItems.Count() == 0)
        {
            Console.WriteLine("result: 1");
        }
        else
        {
            Array asList = uniqueItems.ToArray();
            Array.Sort(asList);

            for (int i = 1; i <= 100000; i++)
            {
                if ((int)asList.GetValue(i - 1) != i)

                {
                    Console.WriteLine("result: " + i);
                    break;
                }
            }
        }

你可以試試這樣。

    public static int solution(int[] A)
    {
        int smallest = -1;
        Array.Sort(A);
        if(A[0] > 1)
            return 1;
        for(int i = 0; i < A.Length; i++)
        {
          
            if(A.Length != i+1 && A[i] + 1 != A[i + 1] && A[i+1] > 0)
            {
                smallest = A[i]+1;
                break;
            }
            else if(A[i] > 0 && A.Length == i+1)
            {
                smallest = A[i] + 1;
            }
        }
        return smallest > 0 ? smallest:1;
    }

這是使用O(N)分區后跟O(N)搜索的方法。 這種方法不使用任何額外的存儲,但它確實改變了數組的內容。

這段代碼是從這里轉換而來的。 另見這篇文章

我添加了注釋以嘗試解釋第二階段findSmallestMissing()的工作原理。 我沒有評論分區方法,因為這只是標准分區的一種變體,可能用於快速排序算法。

static class Program
{
    public static void Main()
    {
        Console.WriteLine(FindSmallestMissing(1, 3, 6, 4, 1, 2));
        Console.WriteLine(FindSmallestMissing(1, 2, 3));
        Console.WriteLine(FindSmallestMissing(-1, -3));
    }

    public static int FindSmallestMissing(params int[] array)
    {
        return findSmallestMissing(array, partition(array));
    }

    // Places all the values > 0 before any values <= 0,
    // and returns the index of the first value <= 0.
    // The values are unordered.

    static int partition(int[] arr)
    {
        void swap(int x, int y)
        {
            var temp = arr[x];
            arr[x]   = arr[y];
            arr[y]   = temp;
        }

        int pIndex = 0; // Index of pivot.

        for (int i = 0; i < arr.Length; i++)
        {
            if (arr[i] > 0) // pivot is 0, hence "> 0"
                swap(i, pIndex++);
        }

        return pIndex;
    }

    // This is the clever bit.
    // We will use the +ve values in the array as flags to indicate that the number equal to that index is
    // present in the array, by making the value negative if it is found in the array.
    // This way we can store both the original number AND whether or not the number equal to that index is present
    // in a single value.
    //
    // Given n numbers that are all > 0, find the smallest missing number as follows:
    //
    // For each array index i in (0..n):
    //     val = |arr[i]| - 1;          // Subtract 1 so val will be between 0 and max +ve value in original array.
    //     if (val is in range)         // If val beyond the end of the array we can ignore it
    //     and arr[val] is non-negative // If already negative, no need to make it negative.
    //        make arr[val] negative
    //
    // After that stage, we just need to find the first positive number in the array, which indicates that
    // the number equal to that index + 1 is missing.

    // n = number of values at the start of the array that are > 0
    static int findSmallestMissing(int[] arr, int n)
    {
        for (int i = 0; i < n; i++)
        {
            int val = Math.Abs(arr[i]) - 1;

            if (val < n && arr[val] >= 0)
                arr[val] = -arr[val];
        }

        for (int i = 0; i < n; i++)
        {
            if (arr[i] > 0)   // Missing number found.
                return i + 1;
        }

        return n + 1; // No missing number found.
    }
}
class Program
{
    static void Main(string[] args)
    {
        int [] A = new int[]  {1, 2, 3};
        int n = 0;
        bool found = false;
        Array.Sort(A);
        for (int i = 1; i <= 100000; i++) {
            for (int x = 0; x <= A.Length - 1; x++) {
                int next = (x + 1) < A.Length ? (x + 1): x;
                if (A[x] > 0 && (A[next] - A[x]) > 0) {
                    n = A[x] + 1;
                    found = true;
                    break;
                }
            }

            if(found) {
                break;
            }
        }
        Console.WriteLine("Smallest number: " + n);

    }
}
 int smallestNumber=Enumerable.Range(1,(int.Parse(A.Length.ToString())+1)).Except(A).Min();
    Array.Sort(A);
    for (int number = 1; number <= 100000; number++)
    {
        for (int num = number; i2 <= A.Length - 1; num++)
        {
            if (A[num] == number)

            {
                smallestNumber = A[num] + 1;
                break;
            }

        }
    } 
    return smallestNumber; 
}
using System.Linq;

class Solution {
    public int solution(int[] A) {
        int smallestNumber = Enumerable.Range(1, 100000).Except(A).Min();
        return smallestNumber;
    }
}

最簡單的一個:)

class Solution
{
    public int solution(int[] array)
    {
        int[] onlyPositiveArray = array.Where(a => a > 0).OrderBy(a => a).Distinct().ToArray();

        int smallestNumber = 1;
        foreach (var number in onlyPositiveArray)
        {
            if (smallestNumber  != number)
            {
                break;
            }

            smallestNumber ++;
        }

        if (!onlyPositiveArray.Contains(smallestNumber ))
        {
            return smallestNumber;
        }
        else
        {
            return smallestNumber  + 1;
        }
    }
}

PHP 解決方案:

function solution($A) { // 用 PHP7.0 編寫代碼

// sort array

sort($A);

// get the first 
$smallest = $A[0];


// write while 

while( in_array(($smallest),$A) || (($smallest) < 1 ) )
{

    $smallest++;
}

return $smallest;
 }

我的解決方案,如果有人可以測試它的性能如何?

 public int solution(int[] N) { if (N.Length == 0) return 1; else if (N.Length == 1) return N[0] >= 0? N[0] + 1: 1; Array.Sort(N); int min = Array.Find(N, IsUnderZero); if (min == default) return 1; HashSet < int > hashSet = new HashSet < int > (N); int max = N[N.Length - 1]; for (int i = min + 1; i <= max + 1; i++) { if (.hashSet;Contains(i) && i > 0) return i; } return max + 1; bool IsUnderZero(int i) => i <= 0; }

試試下面的:

 public static int MinIntegerGreaterThanZeroInArray(int[] A)
    {
        int minInt;
        if (A.Length > 0)
        {
            Array.Sort(A);
            for (minInt = 1; minInt <= A.Length; minInt++)
            {
                int index = Array.BinarySearch(A, minInt);
                if (index < 0) return minInt;
            }
            return minInt;
        }
        
        //Array is empty.
        throw new InvalidOperationException();
    }
  public static int Smallest(int[] A)
    {
        int maxPositiveInt = 1;
        HashSet<int> NumDic = new HashSet<int>();
        for (int i = 0; i < A.Length; i++)
        {
            if (A[i] <= 0)
            {
                continue;
            }
            if (!NumDic.Contains(A[i]))
            { 
                NumDic.Add(A[i]); 
            }
            maxPositiveInt = Math.Max(A[i], maxPositiveInt);
        }

        //All numbers are negative
        if (NumDic.Count == 0) 
         {
           return 1;
         }

        int smallestinteger = 1;
        for (int i = 0; i < A.Length; i++)
        {
            if (A[i] <= 0) 
            { 
                continue; 
            }
            if (!NumDic.Contains(smallestinteger))
            {
                return smallestinteger;
            }

            else
            {
                smallestinteger++;
            }
        }

        return maxPositiveInt + 1;
    }
static void Main(string[] args)
    {
        Console.WriteLine(solution(new int[]{1, 3, 6, 4, 1, 2}));
    }
    public static int solution(int[] A)
    {
        Array.Sort(A);
        int smallest = A[0];
        while (A.Contains(smallest+1)|| (smallest+1)<1)
        {
            smallest++;
        }
        return smallest +1;
        
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM