Lesson 71 of 164
Check if an Array Is a Subset of Another
Given two arrays a and b, return true if every element of b also appears in a, meaning b is a subset of a.
Example 1
a = [9, 4, 7, 1, -2, 6, 5], b = [7, 1, -2]
Output: trueExample 2
a = [9, 4, 7, 1, -2, 6, 5], b = [10, 12]
Output: false (10 is not in a)Brute force: search a for each element of b
public class Main {
static boolean contains(int[] a, int x) {
for (int y : a) {
if (y == x) return true;
}
return false;
}
static boolean isSubset(int[] a, int[] b) {
for (int x : b) {
if (!contains(a, x)) return false; // stops at the first missing element
}
return true;
}
public static void main(String[] args) {
int[] a = {9, 4, 7, 1, -2, 6, 5};
System.out.println(isSubset(a, new int[]{7, 1, -2}) + " " + isSubset(a, new int[]{10, 12}));
}
}true falseTime: O(n·m), where n = a.length and m = b.length. Each contains call is a linear scan of a. Java has no contains method on int[], so the helper does the scan. Space: O(1).
The loop returns at the first element that is missing, so a false answer can come back early.
Better: sort a, then binary search
import java.util.Arrays;
public class Main {
static boolean isSubset(int[] a, int[] b) {
int[] sorted = a.clone();
Arrays.sort(sorted);
for (int x : b) {
if (Arrays.binarySearch(sorted, x) < 0) return false; // a negative result means "not found"
}
return true;
}
public static void main(String[] args) {
int[] a = {9, 4, 7, 1, -2, 6, 5};
System.out.println(isSubset(a, new int[]{7, 1, -2}) + " " + isSubset(a, new int[]{10, 12}));
}
}true falseTime: O(n log n + m log n). Space: O(n) for the sorted copy. Arrays.binarySearch needs a sorted array and returns a negative number when the value is absent. Sort a in place instead of copying when memory is tight and changing the input is allowed.
Optimal: put a in a HashSet
Build a set from a once (O(n)), and each membership check becomes O(1) on average. A HashSet<Integer> stores boxed Integer objects, so each int is wrapped automatically on add and contains.
Walkthrough with b = [7, 1, -2]. The set is {9, 4, 7, 1, -2, 6, 5}:
| element of b | in set? |
|---|---|
| 7 | yes |
| 1 | yes |
| -2 | yes → return true |
import java.util.HashSet;
import java.util.Set;
public class Main {
static boolean isSubset(int[] a, int[] b) {
Set<Integer> set = new HashSet<>();
for (int x : a) set.add(x);
for (int x : b) {
if (!set.contains(x)) return false;
}
return true;
}
public static void main(String[] args) {
int[] a = {9, 4, 7, 1, -2, 6, 5};
System.out.println(isSubset(a, new int[]{7, 1, -2}) + " " + isSubset(a, new int[]{10, 12}));
System.out.println(isSubset(a, new int[]{}));
}
}true false
trueTime: O(n + m). Space: O(n) for the set.
Variant: duplicates must be matched
If b = [7, 7] should only count as a subset when a contains two 7s (a multiset subset), count the elements of a and use up one count per element of b. merge(x, 1, Integer::sum) adds 1 to the count of x, or stores 1 when x is absent. getOrDefault(x, 0) reads a count, or 0 when x is absent.
import java.util.HashMap;
import java.util.Map;
public class Main {
static boolean isSubMultiset(int[] a, int[] b) {
Map<Integer, Integer> counts = new HashMap<>();
for (int x : a) {
counts.merge(x, 1, Integer::sum);
}
for (int x : b) {
int left = counts.getOrDefault(x, 0);
if (left == 0) return false;
counts.put(x, left - 1);
}
return true;
}
public static void main(String[] args) {
System.out.println(isSubMultiset(new int[]{7, 1, 7}, new int[]{7, 7}) + " " + isSubMultiset(new int[]{7, 1}, new int[]{7, 7}));
}
}true falseEdge cases
- Empty
b: always a subset. The loop overbdoes not run, so the result istrue. - Empty
awith a non-emptyb:false. - Duplicates in
b: ignored by the set version, and matched one for one by the multiset variant.
