Check for missing number in sequence

前端 未结 14 1537
太阳男子
太阳男子 2020-12-04 17:58

I have an List which contains 1,2,4,7,9 for example.

I have a range from 0 to 10.

Is there a way to determine what numbers are missin

相关标签:
14条回答
  • 2020-12-04 18:04

    this method here returns the number of missing elements ,sort the set , add all elements from range 0 to range max , then remove the original elements , then you will have the missing set

    int makeArrayConsecutive(int[] statues) 
    {
    
    Array.Sort(statues);    
    HashSet<int> set = new HashSet<int>();
    
    for(int i = statues[0]; i< statues[statues.Length -1]; i++)
     {
      set.Add(i);
     }
    
    for (int i = 0; i < statues.Length; i++)
    {
     set.Remove(statues[i]);
    }
    
    var x = set.Count;    
    return x;
    // return set ; // use this if you need the actual elements + change the method return type        
    }
    
    0 讨论(0)
  • 2020-12-04 18:05

    Ok, really, create a new list which parallels the initial list and run the method Except over it...

    I have created a fully linq answer using the Aggregate method instead to find the missings:

    var list = new List<int>(new[] { 1, 2, 4, 7, 9 }); // Assumes list is ordered at this point
    
    list.Insert(0, 0);   // No error checking, just put in the lowest and highest possibles.
    list.Add(10);        // For real world processing, put in check and if not represented then add it/them.
    
    var missing = new List<int>();    // Hold any missing values found.
    
    list.Aggregate ((seed, aggr) =>   // Seed is the previous #, aggr is the current number.
    {
        var diff = (aggr - seed) -1;  // A difference between them indicates missing.
    
        if (diff > 0)                 // Missing found...put in the missing range.
            missing.AddRange(Enumerable.Range((aggr - diff), diff));
    
        return aggr;    
    });
    

    The missing list has this after the above code has been executed:

    3, 5, 6, 8
    
    0 讨论(0)
  • 2020-12-04 18:08

    LINQ's Except method would be the most readable. Whether it performs adequately for you or not would be a matter for testing.

    E.g.

    range.Except(listOfValues);
    

    Edit

    Here's the program I used for my mini-benchmark, for others to plug away with:

    static void Main()
    {
        var a = Enumerable.Range(0, 1000000);
        var b = new List<int>();
    
        for (int i = 0; i < 1000000; i += 10)
        {
            b.Add(i);
        }
    
        Stopwatch sw = new Stopwatch();
        sw.Start();
        var c = a.Except(b).ToList();
        sw.Stop();
        Console.WriteLine("Milliseconds {0}", sw.ElapsedMilliseconds );
        sw.Reset();
    
        Console.ReadLine();
    }
    
    0 讨论(0)
  • 2020-12-04 18:08

    This does not use LINQ but it works in linear time.

    I assume that input list is sorted.

    This takes O(list.Count).

    private static IEnumerable<int> get_miss(List<int> list,int length)
    {
        var miss = new List<int>();
        int i =0;
        for ( i = 0; i < list.Count - 1; i++)
        {
            foreach (var item in 
                         Enumerable.Range(list[i] + 1, list[i + 1] - list[i] - 1))
            {
                yield return item;
            }
    
        }
        foreach (var item in Enumerable.Range(list[i]+1,length-list[i]))
        {
            yield return item;
        }
    }
    

    This should take O(n) where n is length of full range.

     static void Main()
        {
            List<int> identifiers = new List<int>() { 1, 2, 4, 7, 9 };
    
            Stopwatch sw = new Stopwatch();
    
            sw.Start();
            List<int> miss = GetMiss(identifiers,150000);
            sw.Stop();
            Console.WriteLine("{0}",sw.ElapsedMilliseconds);
    
        }
    private static List<int> GetMiss(List<int> identifiers,int length)
    {
        List<int> miss = new List<int>();
    
        int j = 0;
    
        for (int i = 0; i < length; i++)
        {
            if (i < identifiers[j])
                miss.Add(i);
    
            else if (i == identifiers[j])
                j++;
    
            if (j == identifiers.Count)
            {
                miss.AddRange(Enumerable.Range(i + 1, length - i));
                break;
            }
        }
    
        return miss;
    }
    
    0 讨论(0)
  • 2020-12-04 18:09
            List<int> selectedNumbers = new List<int>(){8, 5, 3, 12, 2};
    
            int firstNumber = selectedNumbers.OrderBy(i => i).First();
            int lastNumber = selectedNumbers.OrderBy(i => i).Last();
    
            List<int> allNumbers = Enumerable.Range(firstNumber, lastNumber - firstNumber + 1).ToList();
    
            List<int> missingNumbers = allNumbers.Except(selectedNumbers).ToList();
    
            foreach (int i in missingNumbers)
            {
                Response.Write(i);
            }
    
    0 讨论(0)
  • 2020-12-04 18:14

    Turn the range you want to check into a HashSet:

    public IEnumerable<int> FindMissing(IEnumerable<int> values)
    {
      HashSet<int> myRange = new HashSet<int>(Enumerable.Range(0,10));
      myRange.ExceptWith(values);
      return myRange;
    }
    

    Will return the values that aren't in values.

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