How do I determine if an array contains all the integers in a separate array

送分小仙女□ 提交于 2019-12-01 04:15:56

Here's a recursive way to do this:

public static boolean contains(int[] set1, int[] set2) {
    //System.out.println(Arrays.toString(set1) + " " + Arrays.toString(set2));

    //set 2 cannot be contained within set 1 because there aren't 
    //enough elements. This either means that we recursed too deep
    //within the first set that there are not enough elements, or
    //there were not enough elements to begin with.
    if (set1.length < set2.length) return false;

    //from the start of each set, count the number of matches in order
    int numMatched = 0;
    while (numMatched < set2.length && set1[numMatched] == set2[numMatched]) {
        numMatched++;
    }

    if (numMatched == set2.length) 
        //the number of matches found equals the length of the set to
        //search for, so we have found a match. Return true to unravel
        //the recursion.
        return true;
    else {
        //we didn't find a match, so shift the array by 1 and then
        //recursively call this function to compare again.
        int[] subset = Arrays.copyOfRange(set1,  1,  set1.length);
        return contains(subset, set2);
    }

}

Each time we fail to find the matching sequence, we create a subset of the array, excluding the first element, and pass that back to contains to continue the checks.Here is an output of each iteration:

First time: set1 = [1, 6, 2, 1, 4, 1, 2, 1, 8] and set2 = [1, 2, 1] No match is found at the beginning of the array (we break out when comparing 6 and 2. The next recursive call is this:

set1= [6, 2, 1, 4, 1, 2, 1, 8], [1, 2, 1]

the next recursion compares [2, 1, 4, 1, 2, 1, 8] [1, 2, 1]

and so on until the final recursion compares: [1, 2, 1, 8] [1, 2, 1] and finds the match in order.

For consecutive

public static boolean contains(int[] set1, int[] set2) {
     OUTER:
     for (int i = 0; i < set1.length - set2.length; i++) {
         for (int j = 0; j < set2.length; j++) {
             if (set1[i + j] != set2[j])
                  continue OUTER;
         }
         return true;
     } 
     return false;
}

To avoid a label you can use a method which might be clearer

public static boolean contains(int[] set1, int[] set2) {
     for (int i = 0; i < set1.length - set2.length; i++)
         if (!matches(set1, i, set2))
             return false;
     return true;
}

public static boolean matches(int[] set1, int off, int[] set2) {
     for (int j = 0; j < set2.length; j++)
         if (set1[off + j] != set2[j])
               return false;
     return true;
}

If it only needs to be in order

public static boolean contains(int[] set1, int[] set2) {
     for (int i = 0, j = 0; i < set1.length; i++)
         if (set1[i] == set2[j]) 
             if (++j >= set2.length)
                 return true;
     return false;
}

I would say that as far as the mentality, you should think "work the first element against the array until a match".

public static boolean contains(int[] set1, int[] set2) {
    for (int i = 0; i < set1.length; i++) {
       int count = 0;
       for (int w = 0; w < set2.length; w++) {
          if (set2[w] == set1[i + w]) {
              count++;
          } else {
              count = 0;
              continue;
          }
       }
       if (count == set2.length) {
           return true;
       }
    }
    return false;

In this sense, you will only advance as far down your second array for comparison as needed. If, after going through all the elements in set2, you end up with the same length, then it's contained within set1. And of course, ask if you have questions :)

Start with int first=list2[0]; then find that number in list1. Next, loop over all values in list2 and simultaneously loop through list1 from the previously-found position until either the entire list2 is verified present in list1 or a discrepancy is found. Restart with first after the previously-found location if a discrepancy is found.

Shamelessly copying another answer with a tweak:

public static boolean contains(int[] set1, int[] set2) {
    for (int i = 0, j = 0; i < set1.length; i++) {
        if (set1[i] == set2[j]) {
            if (++j >= set2.length)
                return true;
        }
        else {
            i -= j;
            j = 0;
        }
    }
    return false;
}

This consecutive-version mechanism also ensures that no overruns occur without any extra checks.

Demo of this answer at IDEOne.com

I came up with the following function. Read the comments to understand the logic behind it:

public static boolean contains(int[] a, int[] b) {
    //Loop until there aren't enough elements left in a to match b.
    for (int i = 0; i < a.length - b.length + 1; i++) {
        for (int j = 0; j < b.length; j++) {

            //If the jth element of b doesn't match
            //the corresponding element of a, then move
            //to the next step in the sequence.
            if (a[i + j] != b[j])
                break;

            //If we are at the end of the loop, return
            //true because that means we found a consecutive match.
            if (j == b.length - 1)
                return true;

        }
    }

    return false; //If we got here, there are no matches.
}

I thought about it and came up with this solution:

static boolean contains(final int[] list1, final int[] list2) {
  final int limit = list1.length - list2.length + 1; // we do not need to check an index >= limit, because list2 wouldn't fit anymore at this point

  for (int indexL1 = 0, indexL2 = 0; indexL1 < limit; ++indexL1) {
    while (list1[indexL1 + indexL2] == list2[indexL2]) { // check all matches from here
      ++indexL2;
      if (indexL2 == list2.length) { // if all of list2 matched so far, we found it
        return true;
      }
    }
    indexL2 = 0; // we did not find it, start from beginning of list2 again
  }

  return false; // no match found
}

I call it the Lawrey-Solution.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!