How to quickly find out if a list contains a list?

There are several related questions, but I'm looking for a solution specific to my case. There is an array (usually) of 14 integers, each of which is in the range from 1 to 34. How can I quickly say if every int in a particular static list appears at least once in this array?

For reference, I am currently using this code, which was written as close to the specification as possible, so it can be greatly improved:

if (array.Count < 13) {
    return;
}

var required = new int[] {
    0*9 + 1,
    0*9 + 9,
    1*9 + 1,
    1*9 + 9,
    2*9 + 1,
    2*9 + 9,                
    3*9 + 1,
    3*9 + 2,
    3*9 + 3,
    3*9 + 4,
    3*9 + 5,
    3*9 + 6,
    3*9 + 7,
};

IsThirteenOrphans = !required.Except (array).Any ();

The required list is not dynamic, i.e. at run time it will always match. Using Linq is optional, the main aspect is performance.

Edit:

  • The input array is not sorted.
  • Input values ​​may appear several times.
  • 14 , .. 1 .
  • 1 .
  • , , .
  • , .

: .

+5
7

1
required, , . , , , . , .

:

for(int i = 0; i < 14; i++)
  if(arr[i] != required[i]) return false;

return true;

2
, 14 /, required HashSet

input.Count(i => required.Contains(i)) == 14

, , , .

3
, 14 int require. .

//Prepare/precalculated
int[] hashes = new int[34];
Random random = new Random();
for(int i = 0; i < 34; i++)
  hashes[i] = random.NextInt();

//On each list
int HashInts(int[] ints)
{
  int result = 0;
  foreach(int i in ints)
    result += hashes[i - 1];

  return result;
}

hashes , .

4
:

int[] CreateHistogram(int[] ints)
{
  int[] counts = new int[34];
  foreach(int i in ints)
  {
    counts[i - 1]++;
  }

  return counts;
}

, .

+1

, linq. , if (lst[i] < 35) counting sort:

public bool FindExactMatch(int[] array, List<int> lst)
{
    bool[] a34 = new bool[35];

    foreach(var item in array)
    {
        a34[item] = true;
    }

    int exact = 0;

    for (int i = 0; i < lst.Count; i++)
    {
        if (a34[lst[i]])
        {
            exact++;
            if (exact == array.Length) return true;

            a34[lst[i]] = false;
        }
    }

    return false;
}

, , lst.BinarySearch(array[i]), 14 * log (n) * c1, , , , , , t , Min, Max, Sort linq ( 4 10 ) () . , , , c1 .

+1

34- , C, V ( v [0], v [1],... V (1 < v [0]) | (1 < v [1])... 1 , V) S , . , , , (S ~ V) == 0.

+1

- . 1-34 , :

int[] counts = new int[34];

1 3s, [0] == 1 && counts [2] = 2 ( 1, ( .))

, , int , x , count [x] > 0. , counts , , . , / ; .

+1

, , 1 34. const ulong. ulong, , .

const ulong comparator = (1UL << 1) | (1UL << 9) | (1UL << 10) | (1UL << 18) | (1UL << 19) | (1UL << 27) | (1UL << 28) | (1UL << 29) | (1UL << 30) | (1UL << 31) | (1UL << 32) | (1UL << 33) | (1UL << 34);

public static bool ContainsDistinct13Values(int[] array)
{
    ulong word = 0;
    foreach (int i in array)
    {
        word |= (1UL << i);
    }
    return word == comparator;
}
+1

, - . , , - .

bool notContains = false;

foreach (var iddd in required)
{
    foreach (var ar in array)
    {
        if (iddd == ar) notContains=true;
    }

    if (notContains == false) break;
}

, . . 5 , 0

System.Diagnostics.Stopwatch aTimer = new System.Diagnostics.Stopwatch();
aTimer.Start();

var IsThirteenOrphans = !required.Except(array).Any();
aTimer.Stop();

System.Diagnostics.Stopwatch bTimer = new System.Diagnostics.Stopwatch();
bTimer.Start();
bool notContains = false;

foreach (var iddd in required)
{
    foreach (var ar in array)
    {
        if (iddd == ar) notContains=true;            
    }

    if (notContains == false) break;
}

bTimer.Stop();
0

Edit: So I understood your question and probably had some nice complicated solution. Another question: how good is its performance.

static void Main(string[] args)
{
    var required = new int[]
                       {
                           0*9 + 1,
                           0*9 + 9,
                           1*9 + 1,
                           1*9 + 9,
                           2*9 + 1,
                           2*9 + 9,
                           3*9 + 1,
                           3*9 + 2,
                           3*9 + 3,
                           3*9 + 4,
                           3*9 + 5,
                           3*9 + 6,
                           3*9 + 7,
                       };

    precomputed = required.Select((x, i) => new { Value = x, Offset = (UInt16)(1 << i) }).ToDictionary(x => x.Value, x => x.Offset);

    for (int i = 0; i < required.Length; i++)
    {
        precomputedResult |= (UInt16)(1 << i);
    }

    int[] array = new int[34]; // your array goes here..
    Console.WriteLine(ContainsList(array));

    Console.ReadKey();
}

// precompute dictionary
private static Dictionary<int, UInt16> precomputed;
// precomputed result
private static UInt16 precomputedResult = 0;

public static bool ContainsList(int[] values)
{
    UInt16 result = 0;
    for (int i = 0; i < values.Length; i++)
    {
        UInt16 v;
        if (precomputed.TryGetValue(values[i], out v))
            result |= v;
    }

    return result == precomputedResult;
}
0
source

All Articles