Given a set of distinct integers, S, return all possible subsets.
Note: 1) Elements in a subset must be in non-descending order. 2) The solution set must not contain duplicate subsets.
For example, given S = [1,2,3], the method returns: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
Thoughts
Given a set S of n distinct integers, there is a relation between Sn and Sn-1. The subset of Sn-1 is the union of {subset of Sn-1} and {each element in Sn-1 + one more element}. Therefore, a Java solution can be quickly formalized.
Java Solution
public ArrayList<ArrayList<Integer>> subsets(int[] S) { if (S == null) return null; Arrays.sort(S); ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>(); for (int i = 0; i < S.length; i++) { ArrayList<ArrayList<Integer>> temp = new ArrayList<ArrayList<Integer>>(); //get sets that are already in result for (ArrayList<Integer> a : result) { temp.add(new ArrayList<Integer>(a)); } //add S[i] to existing sets for (ArrayList<Integer> a : temp) { a.add(S[i]); } //add S[i] only as a set ArrayList<Integer> single = new ArrayList<Integer>(); single.add(S[i]); temp.add(single); result.addAll(temp); } //add empty set result.add(new ArrayList<Integer>()); return result; } |
Hi Guys, I made a small video explaining the simple recursive and backtracking solution for this. Please check this out:)
https://www.youtube.com/watch?v=-eVkq8odxno&t=27s
“`
public ArrayList<ArrayList> get(int[] input) {
ArrayList<ArrayList> result = new ArrayList();
result.add(new ArrayList(Arrays.asList(input[0])));
for (int i = 1; i < input.length; i++) {
int curr = input[i];
int size = result.size();
result.add(new ArrayList(Arrays.asList(curr)));
for (int j = 0; j < size; j++) {
ArrayList temp = new ArrayList();
temp.addAll(result.get(j));
temp.add(curr);
result.add(temp);
}
}
return result;
}
“`
Collections.sort(result, new Comparator<ArrayList>() {
@Override
public int compare(ArrayList a, ArrayList b) {
int an = a.size();
int bn = b.size();
for (int i = 0; i < Math.min(an, bn); i++) {
int cmp = Integer.compare(a.get(i), b.get(i));
if (cmp != 0)
return cmp;
}
return Integer.compare(a.size(), b.size());
}
});
it will work fine now.
the code will give sets in unsorted form, we also have to write a modified comparable func to compare the final sets of result list by comparing first elements of every two sets .
if you designate each element in the array with 0 or 1 (not-present/present), then all possible combinations of binary number with 3 positions is 2^3=8. For n position it is 2^n. Nothing to induct more mathematically other than that.
The code is wrong
actually I wouldn’t go the master theorem way, because for that the ‘aT(n/b)’ term needs to be defined, here a_n = 2a_(n-1) + f(n).. its hard to visualize it in terms of T(n/b), i would simply explain it as for every element i: work done = 2*2^(i-1) [using a_n=2*a_(n-1)] so for a^n=2^n, base case a_0=1 (considering 0 elements, empty subset)
Much simpler in Scala
def allSubsets(S: List[Int]) = {
S.distinct.sorted.foldLeft(List(List.empty[Int])) { (subsets, num) ⇒
subsets ++ subsets.map(_ :+ num)
}
}
I know the time complexity is 2 power n, how do i get there with a mathematical formula? anyone please?, i was asked this in a startup interview today! I tried with masters theorem but couldn’t get there.
Hi,
I’ve got a shorter code for this problem.
public ArrayList<ArrayList> subsets(int[] S) {
ArrayList<ArrayList> ans = new ArrayList<ArrayList>();
ans.add(new ArrayList());
Arrays.sort(S);
for (int i = 0; i < S.length; i ++) {
int curSize = ans.size();
for (int j = 0; j < curSize; j ++) {
ArrayList cur = new ArrayList(ans.get(j));
cur.add(S[i]);
ans.add(cur);
}
}
return ans;
}