Finding all subsets of a given set of distinct integers recursively - algorithm

Given a set of distinct integers, I want to find all the possible subsets (for [1,2,3], the code should print [1], [1,2], [1,3], [1,2,3], [2], [2,3], [3] (not necessarily in that order).
There are a few solutions (like this one) out there but what I want to do is to re-implement the bellow solution with a new recursion and no for loop by passing around the indexes: (start = 0)
public void forSolution(List<List<Integer>> res, int[] nums, List<Integer> list, int start) {
for (int i = start; i < nums.length; i++) {
List<Integer> tmp = new ArrayList<>(list);
tmp.add(nums[i]);
res.add(new ArrayList<>(tmp));
forSolution(res, nums, tmp, i + 1);
}
}
I thought I need to pass two integers to the method, one for keeping the record of index and the other one for keeping the start point, but I am having problem on when I need to do the index increment (vs start increment).
Any help would be appreciated.

I think the algorithm gets easier if you don't bother with indices.
The basic idea is that for any given sublist, each element of the original list is either included or not included. The list of all possible sublists is simply all possible combinations of including / not including each element.
For a recursive implementation, we can consider two cases:
The input list is empty. The empty list only has a single sublist, which is the empty list itself.
The input list consists of a first element x and a list of remaining elements rest. Here we can call our function recursively to get a list of all sublists of rest. To implement the idea of both including and not including x in our results, we return a list consisting of
each element of sublists(rest) with x added at the front, representing all sublists of our original list that contain x, and
each element of sublists(rest) as is (without x), representing all sublists of our original list that don't contain x.
For example, if the list is [1, 2, 3], we have x = 1 and rest = [2, 3]. The recursive call sublists(rest) produces [2, 3], [2], [3], []. For each of those sublists we
prepend x (which is 1), giving [1, 2, 3], [1, 2], [1, 3], [1], and
don't prepend x, giving [2, 3], [2], [3], [].
Concatenating those parts gives our total result as [1, 2, 3], [1, 2], [1, 3], [1], [2, 3], [2], [3], [].
Sample implementation:
use strict;
use warnings;
sub sublists {
if (!#_) {
return [];
}
my $x = shift #_;
my #r = sublists(#_);
return (map [$x, #$_], #r), #r;
}
for my $sublist (sublists 1, 2, 3) {
print "[" . join(", ", #$sublist) . "]\n";
}
Output:
[1, 2, 3]
[1, 2]
[1, 3]
[1]
[2, 3]
[2]
[3]
[]

Related

What is the time complexity of a function that generates combinations of length r from n elements without repetitions or permutations?

The following function takes in a list of elements src as well as a combination length r. It prints out all possible combinations of length r, without repetition of an element inside a combination or repetition of a combination in a different order (permutation).
void fn(List<dynamic> src, int r, List<dynamic> tmp) {
for (var i = 0; i < src.length; i++) {
tmp.add(src.removeAt(i));
if (tmp.length == r) print(tmp.toString());
else if (i < src.length) fn(src.sublist(i), r, tmp);
src.insert(i, tmp.removeLast());
}
}
So, given n = [1,2,3,4,5] and r = 3, it would print out
[1, 2, 3]
[1, 2, 4]
[1, 2, 5]
[1, 3, 4]
[1, 3, 5]
[1, 4, 5]
[2, 3, 4]
[2, 3, 5]
[2, 4, 5]
[3, 4, 5]
How would you describe the time complexity of this function in Big O notation? Clearly both the length of src as well as r have to be taken into account. If I am not mistaken, the time complexity of a similar function printing out all combinations with repetitions and permutations would be O(n^r). But what is it in this case?
According to Stef's comment, the time complexity seems to be O(r(n choose r)).

Find all lists of sublists that when concatenated give a given list

I wrote this function that given as a first parameter a list of lists, it generates in the second parameter the result of concatenating all the lists.
appall([],[]).
appall([H|T],V) :- appall(T,V1), append(H,V1,V).
However, I want it to work the other way around - appall(X,[1,2,3]) - to give me X = [[],[1,2,3]] then X=[[1],[2,3]] and so on. This doesn't work because the call appall(T, V1) doesn't decrease.
How do I fix it?
Here is one solution:
split([],[]).
split([Head|Tail],[[Head]|Split]) :-
split(Tail,Split).
split([Head|Tail],[[Head|List]|Split]) :-
split(Tail,[List|Split]).
For example:
?- split([1,2,3,4],Lists), split(Recover,Lists).
Lists = [[1], [2], [3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1], [2], [3, 4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1], [2, 3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1], [2, 3, 4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2], [3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2], [3, 4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2, 3], [4]],
Recover = [1, 2, 3, 4] ;
Lists = [[1, 2, 3, 4]],
Recover = [1, 2, 3, 4] ;
false.
This solution is based on the following observation. I will refer to the flattened list as the input list and the unflattened list as the output list. In the recursive case, the input list has the form [H|T] and split(T,R) succeeds by assumption. There are three cases to consider.
If R = [] we can begin constructing a new list whose last element is H.
If R = [_|_] we can begin constructing a new list whose last element is H.
If R = [L|_] we can continue constructing L by prepending H to L.
In each case, we obtain valid output lists. The first two cases are implemented by the second clause of split/2 (it doesn't matter whether R = [] or R = [_|_]) and the third by the third clause.

Generate a filtered subset of repeated permutations of an array of objects (with given length k)

I'm new to Ruby. I need to generate all combinations of objects based on a length.
For example, array = [obj1, obj2, obj3], length = 2, then combinations are:
[
[obj1, obj1],
[obj1, obj2],
[obj1, obj3],
# ...
[obj3, obj3]
]
I know I can use repeated_permutation method for this problem, but I need also to be able to filter some permutations. For example, to filter out permutations where 2 identical objects are one after another, i.e. like this [obj1, obj1].
If all you need is to remove any pairs that are the same obj, you can simply use the permutation method.
arr = [1,2,3]
arr.permutation(2).to_a
#=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]
Given an arbitrary input array:
a = [1, 2, 3, 3, 4]
If you only wish to generate the unique permutations, then you can simply do:
a.uniq.permutation(2)
(uniq is not needed, if you know the initial array contains unique elements!)
However, as a more general solution, you must do:
a.repeated_permutation(2).reject { |permutation| ** FILTER RULE GOES HERE ** }
So for example, if you wish to filter all results which do not have two consecutive repeated values, then you can do:
a.repeated_permutation(2).reject do |permutation|
permutation.each_cons(2).any? {|x, y| x == y}
end
Taking this to the extreme, here is a generalised method:
def filtered_permutations(array, length)
array.repeated_permutation(length).reject{|permutation| yield(permutation)}
end
# Or, if you prefer:
def filtered_permutations(array, length, &block)
array.repeated_permutation(length).reject(&block)
end
# Usage:
a = [1, 2, 3, 3, 4]
filtered_permutations(a, 2) {|permutation| permutation.each_cons(2).any? {|x, y| x == y} }
# Or, if you prefer:
filtered_permutations(a, 2) {|permutation| permutation.each_cons(2).any? {|consecutive| consecutive.uniq.one?} }
Pass a block where you perform your "filtering". So to remove those with identical elements you'd go with:
a = [1,2,3]
a.repeated_permutation(2).reject { |permutation| permutation.uniq.one? }
#=> [[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]

Algorithm to find a sequence of sub-sequences

Sequence [1,2,3] consider. This sequence has the following 6 different sequence: [1]and [2]and [3] and [1,2] and [2,3] and [1,2,3]
Note! Length the initial sequence may be up to 100 digits.
Please help me. How can I make the following sequences?
I love researching more about this kind of algorithms. Please tell me the name of this type of algorithms.
Here is a c code to print all sub sequences. Algorithm uses nested loops.
#include<stdio.h>
void seq_print(int A[],int n)
{
int k;
for(int i =0;i<=n-1;i++)
{
for(int j=0;j<=i;j++)
{
k=j;
while(k<=i)
{
printf("%d",A[k]);
k++;
}
printf("\n");
}
}
}
void main()
{
int A[]={1,2,3,4,5,6,7,8,9,0};
int n=10;
seq_print(A,n);
}
Your problem can be reduced to the Combination problem. There are already many solutions existed in stackoverflow. You can check this, it may be useful for you.
It is called a power set (in your case the empty set is excluded).
To build a power set, start with a set with an empty set in it; then
for each item in the input set extend the power set with all its subsets accumulated so far
with the current item included (in Python):
def powerset(lst):
S = [[]]
for item in lst:
S += [subset + [item] for subset in S]
return S
Example:
print(powerset([1, 2, 3]))
# -> [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
To avoid producing all subsets at once, a recursive definition could be used:
a power set of an empty set is a set with an empty set in it
a power set of a set with n items contains all subsets from a power set
of a set with n - 1 items plus all these subsets with the n-th item included.
def ipowerset(lst):
if not lst: # empty list
yield []
else:
item, *rest = lst
for subset in ipowerset(rest):
yield subset
yield [item] + subset
Example:
print(list(ipowerset([1, 2, 3])))
# -> [[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]
Yet another way to generate a power set is to generate r-length subsequences (combinations) for all r from zero to the size of the input set (itertools recipe):
from itertools import chain, combinations
def powerset_comb(iterable):
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
Example:
print(list(powerset_comb([1, 2, 3])))
# -> [(), (1,), (2,), (3,), (1,2), (1,3), (2,3), (1,2,3)]
See also what's a good way to combinate through a set?.

Intersect each array in a array - Ruby

I want to find the intersect of each array elements in a array and take the intersection.
The inputs are array of arrays e.g., "'list_arrays' as mentioned in this script below"
The 'filter' is a limit needed to be applied on the total length of intersections observed
The out put is expected as array like this "[[2,4]]"
list_arrays = [[1, 2, 3, 4], [2, 5, 6], [1, 5, 8], [8, 2, 4]]
filter = 2
first_element_array = Array.new
list_arrays.each_with_index do |each_array1, index1|
list_arrays.each_with_index do |each_array2, index2|
unless index1 < index2
intersection = each_array1 & each_array2
if intersection.length == filter.to_i
first_element_array.push(intersection)
end
end
end
end
puts first_element_array
This above procedure takes long execution time as I have too long array of array (In million lines). I need a simple rubistic way to handle this problem. Anyone have any simple idea for it?
Deciphering your code it seems what you are asking for is "Return the intersections between pair combinations of a collection if that intersection has a certain size (2 in the example)". I'd write (functional approach):
list_arrays = [[1, 2, 3, 4], [2, 5, 6], [1, 5, 8], [8, 2, 4]]
list_arrays.combination(2).map do |xs, ys|
zs = xs & ys
zs.size == 2 ? zs : nil
end.compact
#=> [[2, 4]]
Proposed optimizations: 1) Use sets, 2) Use a custom abstraction Enumerable#map_compact (equivalent to map+compact but it would discard nils on the fly, write it yourself). 3) Filter out subarrays which won't satisfy the predicate:
require 'set'
xss = list_arrays.select { |xs| xs.size >= 2 }.map(&:to_set)
xss.combination(2).map_compact do |xs, ys|
zs = xs & ys
zs.size == 2 ? zs : nil
end
#=> [#<Set: {2, 4}>]

Resources