Related
I can't change elements of array using anonymous function:
var collection=[0, 1, 2];
collection.forEach((c)=> c+=1);
print(collection);
This variant doesn't work eithter:
var collection = [0, 1, 2];
for (var x in collection) {
x=x+1;
}
print(collection);
If you wish to replace/update all items in a list (List<int> items = [1, 2, 3]):
items = items.map((x) => x + 1).toList();
for (int i = 0; i < items.length; i++) items[i] += 1;
items = List<int>.generate(items.length, (i) => items[i] + 1);
List<int> tempItems = [];
items.forEach((x) => tempItems.add(x + 1));
items = tempItems;
You can't change the arguments to a function or var-in loop. You can call methods on them, which might have the side effect of mutating them, but assigning directly to them will not alter the value from which they are effectively copied.
collection.forEach((c)=> c+=1);
In above line you are incrementing parameter by 1 and that will not affect to the list.
It's equavalent to:
collection.forEach((int c) {// in this case int because list contains int's
c = c + 1;
});
As you can see, no point of changing the value of a parameter(local variable).
Since it's 0,1,2, you can do like this: collection.forEach((c)=> collection[c] = c+1);. That is stupid way because whenever you change any value, you will get an error(out of range).
So, here are some ways that you can change list values:
The easy way:
void main() {
var collection=[0, 1, 2];
for(int i = 0; i < collection.length; i++) {
collection[i] += 1;
}
print(collection);
}
Using replaceRange:
void main() {
var collection=[0, 1, 2];
var temp = collection.map((c) => c+1).toList();
collection.replaceRange(0, collection.length, temp);
print(collection);
}
I have an unsorted array, what is the best method to remove all the duplicates of an element if present?
e.g:
a[1,5,2,6,8,9,1,1,10,3,2,4,1,3,11,3]
so after that operation the array should look like
a[1,5,2,6,8,9,10,3,4,11]
Check every element against every other element
The naive solution is to check every element against every other element. This is wasteful and yields an O(n2) solution, even if you only go "forward".
Sort then remove duplicates
A better solution is sort the array and then check each element to the one next to it to find duplicates. Choose an efficient sort and this is O(n log n).
The disadvantage with the sort-based solution is order is not maintained. An extra step can take care of this however. Put all entries (in the unique sorted array) into a hashtable, which has O(1) access. Then iterate over the original array. For each element, check if it is in the hash table. If it is, add it to the result and delete it from the hash table. You will end up with a resultant array that has the order of the original with each element being in the same position as its first occurrence.
Linear sorts of integers
If you're dealing with integers of some fixed range you can do even better by using a radix sort. If you assume the numbers are all in the range of 0 to 1,000,000 for example, you can allocate a bit vector of some 1,000,001. For each element in the original array, you set the corresponding bit based on its value (eg a value of 13 results in setting the 14th bit). Then traverse the original array, check if it is in the bit vector. If it is, add it to the result array and clear that bit from the bit vector. This is O(n) and trades space for time.
Hash table solution
Which leads us to the best solution of all: the sort is actually a distraction, though useful. Create a hashtable with O(1) access. Traverse the original list. If it is not in the hashtable already, add it to the result array and add it to the hash table. If it is in the hash table, ignore it.
This is by far the best solution. So why the rest? Because problems like this are about adapting knowledge you have (or should have) to problems and refining them based on the assumptions you make into a solution. Evolving a solution and understanding the thinking behind it is far more useful than regurgitating a solution.
Also, hash tables are not always available. Take an embedded system or something where space is VERY limited. You can implement an quick sort in a handful of opcodes, far fewer than any hash table could be.
This can be done in amortized O(n) using a hashtable-based set.
Psuedo-code:
s := new HashSet
c := 0
for each el in a
Add el to s.
If el was not already in s, move (copy) el c positions left.
If it was in s, increment c.
If you don't need to keep the original object you can loop it and create a new array of unique values. In C# use a List to get access to the required functionality. It's not the most attractive or intelligent solution, but it works.
int[] numbers = new int[] {1,2,3,4,5,1,2,2,2,3,4,5,5,5,5,4,3,2,3,4,5};
List<int> unique = new List<int>();
foreach (int i in numbers)
if (!unique.Contains(i))
unique.Add(i);
unique.Sort();
numbers = unique.ToArray();
Treat numbers as keys. for each elem in array:
if hash(elem) == 1 //duplicate
ignore it
next
else
hash(elem) = 1
add this to resulting array
end
If you know about the data like the range of numbers and if it is finite, then you can initialize that big array with ZERO's.array flag[N] //N is the max number in the array
for each elem in input array:
if flag[elem - 1] == 0
flag[elem - 1] = 1
add it to resulatant array
else
discard it //duplicate
end
indexOutput = 1;
outputArray[0] = arrayInt[0];
int j;
for (int i = 1; i < arrayInt.length; i++) {
j = 0;
while ((outputArray[j] != arrayInt[i]) && j < indexOutput) {
j++;
}
if(j == indexOutput){
outputArray[indexOutput] = arrayInt[i];
indexOutput++;
}
}
Use a Set implementation.
HashSet,TreeSet or LinkedHashSet if its Java.
This is a code segment i created in C++, Try out it
#include <iostream>
using namespace std;
int main()
{
cout << " Delete the duplicate" << endl;
int numberOfLoop = 10;
int loopCount =0;
int indexOfLargeNumber = 0;
int largeValue = 0;
int indexOutput = 1;
//Array to hold the numbers
int arrayInt[10] = {};
int outputArray [10] = {};
// Loop for reading the numbers from the user input
while(loopCount < numberOfLoop){
cout << "Please enter one Integer number" << endl;
cin >> arrayInt[loopCount];
loopCount = loopCount + 1;
}
outputArray[0] = arrayInt[0];
int j;
for (int i = 1; i < numberOfLoop; i++) {
j = 0;
while ((outputArray[j] != arrayInt[i]) && j < indexOutput) {
j++;
}
if(j == indexOutput){
outputArray[indexOutput] = arrayInt[i];
indexOutput++;
}
}
cout << "Printing the Non duplicate array"<< endl;
//Reset the loop count
loopCount =0;
while(loopCount < numberOfLoop){
if(outputArray[loopCount] != 0){
cout << outputArray[loopCount] << endl;
}
loopCount = loopCount + 1;
}
return 0;
}
My solution(O(N)) does not use additional memory, but array must been sorted(my class using insertion sort algorithm, but it doesn't matter.):
public class MyArray
{
//data arr
private int[] _arr;
//field length of my arr
private int _leght;
//counter of duplicate
private int countOfDup = 0;
//property length of my arr
public int Length
{
get
{
return _leght;
}
}
//constructor
public MyArray(int n)
{
_arr = new int[n];
_leght = 0;
}
// put element into array
public void Insert(int value)
{
_arr[_leght] = value;
_leght++;
}
//Display array
public void Display()
{
for (int i = 0; i < _leght; i++) Console.Out.Write(_arr[i] + " ");
}
//Insertion sort for sorting array
public void InsertSort()
{
int t, j;
for (int i = 1; i < _leght; i++)
{
t = _arr[i];
for (j = i; j > 0; )
{
if (_arr[j - 1] >= t)
{
_arr[j] = _arr[j - 1];
j--;
}
else break;
}
_arr[j] = t;
}
}
private void _markDuplicate()
{
//mark duplicate Int32.MinValue
for (int i = 0; i < _leght - 1; i++)
{
if (_arr[i] == _arr[i + 1])
{
countOfDup++;
_arr[i] = Int32.MinValue;
}
}
}
//remove duplicates O(N) ~ O(2N) ~ O(N + N)
public void RemoveDups()
{
_markDuplicate();
if (countOfDup == 0) return; //no duplicate
int temp = 0;
for (int i = 0; i < _leght; i++)
{
// if duplicate remember and continue
if (_arr[i] == Int32.MinValue) continue;
else //else need move
{
if (temp != i) _arr[temp] = _arr[i];
temp++;
}
}
_leght -= countOfDup;
}
}
And Main
static void Main(string[] args)
{
Random r = new Random(DateTime.Now.Millisecond);
int i = 11;
MyArray a = new MyArray(i);
for (int j = 0; j < i; j++)
{
a.Insert(r.Next(i - 1));
}
a.Display();
Console.Out.WriteLine();
a.InsertSort();
a.Display();
Console.Out.WriteLine();
a.RemoveDups();
a.Display();
Console.ReadKey();
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class testing {
public static void main(String[] args) {
EligibleOffer efg = new EligibleOffer();
efg.setCode("1234");
efg.setName("hey");
EligibleOffer efg1 = new EligibleOffer();
efg1.setCode("1234");
efg1.setName("hey1");
EligibleOffer efg2 = new EligibleOffer();
efg2.setCode("1235");
efg2.setName("hey");
EligibleOffer efg3 = new EligibleOffer();
efg3.setCode("1235");
efg3.setName("hey");
EligibleOffer[] eligibleOffer = { efg, efg1,efg2 ,efg3};
removeDupliacte(eligibleOffer);
}
public static EligibleOffer[] removeDupliacte(EligibleOffer[] array) {
List list = Arrays.asList(array);
List list1 = new ArrayList();
int len = list.size();
for (int i = 0; i <= len-1; i++) {
boolean isDupliacte = false;
EligibleOffer eOfr = (EligibleOffer) list.get(i);
String value = eOfr.getCode().concat(eOfr.getName());
if (list1.isEmpty()) {
list1.add(list.get(i));
continue;
}
int len1 = list1.size();
for (int j = 0; j <= len1-1; j++) {
EligibleOffer eOfr1 = (EligibleOffer) list1.get(j);
String value1 = eOfr1.getCode().concat(eOfr1.getName());
if (value.equals(value1)) {
isDupliacte = true;
break;
}
System.out.println(value+"\t"+value1);
}
if (!isDupliacte) {
list1.add(eOfr);
}
}
System.out.println(list1);
EligibleOffer[] eligibleOffer = new EligibleOffer[list1.size()];
list1.toArray(eligibleOffer);
return eligibleOffer;
}
}
Time O(n) space O(n)
#include <iostream>
#include<limits.h>
using namespace std;
void fun(int arr[],int size){
int count=0;
int has[100]={0};
for(int i=0;i<size;i++){
if(!has[arr[i]]){
arr[count++]=arr[i];
has[arr[i]]=1;
}
}
for(int i=0;i<count;i++)
cout<<arr[i]<<" ";
}
int main()
{
//cout << "Hello World!" << endl;
int arr[]={4, 8, 4, 1, 1, 2, 9};
int size=sizeof(arr)/sizeof(arr[0]);
fun(arr,size);
return 0;
}
public class RemoveDuplicateArray {
public static void main(String[] args) {
int arr[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 2, 3, 4, 9 };
int size = arr.length;
for (int i = 0; i < size; i++) {
for (int j = i+1; j < size; j++) {
if (arr[i] == arr[j]) {
while (j < (size) - 1) {
arr[j] = arr[j + 1];
j++;
}
size--;
}
}
}
for (int i = 0; i < size; i++) {
System.out.print(arr[i] + " ");
}
}
}
output - 1 2 3 4 5 6 7 9
You can use the "in" and "not in" syntax in python which makes it pretty straight forward.
The complexity is higher than the hashing approach though since a "not in" is equivalent to a linear traversal to find out whether that entry exists or not.
li = map(int, raw_input().split(","))
a = []
for i in li:
if i not in a:
a.append(i)
print a
I am doing it in Python.
array1 = [1,2,2,3,3,3,4,5,6,4,4,5,5,5,5,10,10,8,7,7,9,10]
array1.sort() # sorting is must
print(array1)
current = NONE
count = 0
# overwriting the numbers at the frontal part of the array
for item in array1:
if item != current:
array1[count] = item
count +=1
current=item
print(array1)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 5, 5, 5, 5, 6, 7, 7, 8, 9, 10, 10, 10]
print(array1[:count])#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
The most Efficient method is :
array1 = [1,2,2,3,3,3,4,5,6,4,4,5,5,5,5,10,10,8,7,7,9,10]
array1.sort()
print(array1)
print([*dict.fromkeys(array1)])#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
#OR#
aa = list(dict.fromkeys(array1))
print( aa)#[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
use an dictionary array and add each items as key
if an item was duplicated , dictionary avoid to add it!
it's the best solution
int[] numbers = new int[] {1,2,3,4,5,1,2,2,2,3,4,5,5,5,5,4,3,2,3,4,5};
IDictionary<int, string> newArray = new Dictionary<int, string>();
for (int i = 0; i < numbers.count() ; i++)
{
newArray .Add(numbers[i] , "");
}
I'm developing a 2D map editor for a game and I need a way to increase or decrease the size of the grid/map uniformly in all directions.
Suppose you have a 3x3 map with a sort of "cross" symbol.
(arrays are zero-indexed. They start with 0)
Like this:
0,1,0
1,1,1
0,1,0
The array would look like this:
map = [0,1,0,1,1,1,0,1,0]
So, tile index 4 would be the center of the map.
I'd like to increase the size from 3x3 to 5x5 for example. So I end up with this:
0,0,0,0,0
0,0,1,0,0
0,1,1,1,0
0,0,1,0,0
0,0,0,0,0
The new map array should end up like this:
map = [0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0]
What's a good way of doing this?
Here are two functions for increase and decrease. The parameter arr is your one-dimensional map and xWidth is the width (and of course the height) of your grid.
I had a question with a similar background here on Stackoverflow so many thanks to willywonka_dailyblah who helped me on the j and i indices.
public int[] increase_grid(int[] arr, int xWidth)
{
int newWidth = (xWidth+2);
int[] result = new int[newWidth * newWidth];
int count=0;
while(count<newWidth)
{
result[count++] = 0;
}
for (int i=0;i<xWidth;i++)
{
result[count++] = 0;
for (int j=0;j<xWidth;j++)
{
result[count++] = arr[i * xWidth + j];
}
result[count++] = 0;
}
while(count<(newWidth*newWidth))
{
result[count++] = 0;
}
return result;
}
public int[] decrease_grid(int[] arr, int xWidth)
{
int newWidth = (xWidth-2);
int[] result = new int[newWidth*newWidth];
for(int i=0; i< newWidth;i++)
{
for (int j=0;j< newWidth;j++)
{
result[i* newWidth + j] = arr[(i+1) * xWidth + (j+1)];
}
}
return result;
}
And I have this print function:
public void print_arr(int[] a, int xWidth)
{
for(int i=0;i<xWidth;i++)
{
for(int j=0;j<xWidth;j++)
{
System.out.print(a[i * xWidth + j]+" ");
}
System.out.println();
}
System.out.println();
}
You call these functions like:
int[] map = new int[]{0,1,0,1,1,1,0,1,0};
print_arr(map, 3);
map = increase_grid(map, 3);
print_arr(map, 5);
map = increase_grid(map, 5);
print_arr(map, 7);
map = decrease_grid(map, 7);
print_arr(map, 5);
So you have to pass the current size of your map and either call increase or decrease. Beware, that the these functions include a nested for-loop. Thus, they are less scale-able on greater grid sizes. I think there may be a solution to wrap even this into a loop-sequence, which runs without nesting.
Given a set {1,2,3,4,5...n} of n elements, we need to find all subsets of length k .
For example, if n = 4 and k = 2, the output would be {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}.
I am not even able to figure out how to start. We don't have to use the inbuilt library functions like next_permutation etc.
Need the algorithm and implementation in either C/C++ or Java.
Recursion is your friend for this task.
For each element - "guess" if it is in the current subset, and recursively invoke with the guess and a smaller superset you can select from. Doing so for both the "yes" and "no" guesses - will result in all possible subsets.
Restraining yourself to a certain length can be easily done in a stop clause.
Java code:
private static void getSubsets(List<Integer> superSet, int k, int idx, Set<Integer> current,List<Set<Integer>> solution) {
//successful stop clause
if (current.size() == k) {
solution.add(new HashSet<>(current));
return;
}
//unseccessful stop clause
if (idx == superSet.size()) return;
Integer x = superSet.get(idx);
current.add(x);
//"guess" x is in the subset
getSubsets(superSet, k, idx+1, current, solution);
current.remove(x);
//"guess" x is not in the subset
getSubsets(superSet, k, idx+1, current, solution);
}
public static List<Set<Integer>> getSubsets(List<Integer> superSet, int k) {
List<Set<Integer>> res = new ArrayList<>();
getSubsets(superSet, k, 0, new HashSet<Integer>(), res);
return res;
}
Invoking with:
List<Integer> superSet = new ArrayList<>();
superSet.add(1);
superSet.add(2);
superSet.add(3);
superSet.add(4);
System.out.println(getSubsets(superSet,2));
Will yield:
[[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]
Use a bit vector representation of the set, and use an algorithm similar to what std::next_permutation does on 0000.1111 (n-k zeroes, k ones). Each permutation corresponds to a subset of size k.
This is python. Sorry for the spanish ;)
from pprint import pprint
conjunto = [1,2,3,4, 5,6,7,8,9,10]
k = 3
lista = []
iteraciones = [0]
def subconjuntos(l, k):
if k == len(l):
if not l in lista:
lista.append(l)
return
for i in l:
aux = l[:]
aux.remove(i)
result = subconjuntos(aux, k)
iteraciones[0] += 1
if not result in lista and result:
lista.append( result)
subconjuntos(conjunto, k)
print (lista)
print ('cant iteraciones: ' + str(iteraciones[0]))
Check out my solution
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
public class Subset_K {
public static void main(String[]args)
{
Set<String> x;
int n=4;
int k=2;
int arr[]={1,2,3,4};
StringBuilder sb=new StringBuilder();
for(int i=1;i<=(n-k);i++)
sb.append("0");
for(int i=1;i<=k;i++)
sb.append("1");
String bin=sb.toString();
x=generatePerm(bin);
Set<ArrayList <Integer>> outer=new HashSet<ArrayList <Integer>>();
for(String s:x){
int dec=Integer.parseInt(s,2);
ArrayList<Integer> inner=new ArrayList<Integer>();
for(int j=0;j<n;j++){
if((dec&(1<<j))>0)
inner.add(arr[j]);
}
outer.add(inner);
}
for(ArrayList<?> z:outer){
System.out.println(z);
}
}
public static Set<String> generatePerm(String input)
{
Set<String> set = new HashSet<String>();
if (input == "")
return set;
Character a = input.charAt(0);
if (input.length() > 1)
{
input = input.substring(1);
Set<String> permSet = generatePerm(input);
for (String x : permSet)
{
for (int i = 0; i <= x.length(); i++)
{
set.add(x.substring(0, i) + a + x.substring(i));
}
}
}
else
{
set.add(a + "");
}
return set;
}
}
I am working on a 4 element set for test purpose and using k=2. What I try to do is initially generate a binary string where k bits are set and n-k bits are not set. Now using this string I find all the possible permutations of this string. And then using these permutations I output the respective element in the set. Would be great if someone could tell me about the complexity of this problem.
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector<int> v;
vector<vector<int> > result;
void subset(int arr[],int k,int n,int idx){
if(idx==n)
return;
if(k==1){
for(int i=idx;i<n;i++)
{
v.push_back(arr[i]);
result.push_back(v);
v.pop_back();
}
}
for(int j=idx;j<n;j++) {
v.push_back(arr[j]);
subset(arr,k-1,n,j+1);
v.pop_back();
}
}
int main(){
int arr[] = {1,2,3,4,5,6,7};
int k = 4;
int n =sizeof(arr)/sizeof(arr[0]);
subset(arr,k,n,0);
for(int i = 0;i<result.size();i++)
{
for(int j = 0;j<result[i].size();j++)
{
cout << result[i][j] << " ";
}
cout << endl;
}
}
Another intresting solution.
#include<bits/stdc++.h>
using namespace std;
long factorial(int n) { return (n==1|| n==0|| n < 0) ? 1 : n *factorial(n-1) ;}
void printS(int set[],int n,int k)
{
long noofsubset = factorial(n) / (factorial(n-k)*factorial(k));
bitset<32> z ((1 << (k)) - 1);
string s = z.to_string();
int i = 0;
while(i<noofsubset)
{
for (int j = 0; j < n;j++)
{
if(s[(32-n)+j] == '1')
cout << set[j]<<" ";
}
cout << endl;
next_permutation(s.begin(),s.end());
i++;
}
}
void printSubsetsOfArray(int input[], int size) {
int k = 3;
printS(input,size,k) ;
}
Slight improvement for #amit top voted answer:
His code keep checking combinations even when there won't be any chance for them to reach the wanted length. We can stop creating combinations much earlier:
e.g. for [1,2,3,4,5,6,7,8,9,10] , length = 8 , the code will still try all combinations of length 7,6,5,4,3,2,1 although they will obviously just be thrown away, halting only when idx reaches the end of the list.
We can improve the running time by stopping earlier, when we already know the set we build + the optional remaining digits will still be too short.
change :
//unsuccessful stop clause
if (idx == superSet.size()) return;
into:
// unsuccessful stop clause
Integer maxFutureElements = superSet.size() - idx;
if (current.size() + maxFutureElements < length) return;
Please check my solution:-
private static void printPermutations(List<Integer> list, int subSetSize) {
List<Integer> prefixList = new ArrayList<Integer>();
printPermutations(prefixList, list, subSetSize);
}
private static void printPermutations(List<Integer> prefixList, List<Integer> list, int subSetSize) {
if (prefixList.size() == subSetSize) {
System.out.println(prefixList);
} else {
for (int i = 0; i < list.size(); i++) {
Integer removed = list.remove(i);
prefixList.add(removed);
printPermutations(prefixList, list, subSetSize);
prefixList.remove(removed);
list.add(i, removed);
}
}
}
This is similar to String permutations:-
private static void printPermutations(String str) {
printAllPermutations("", str);
}
private static void printAllPermutations(String prefix, String restOfTheString) {
int len = restOfTheString.length();
System.out.println(prefix);
for (int i = 0; i < len; i++) {
printAllPermutations(prefix + restOfTheString.charAt(i), restOfTheString.substring(0, i) + restOfTheString.substring(i + 1, len));
}
}
This is an implemation in F#:
// allSubsets: int -> int -> Set<Set<int>>
let rec allSubsets n k =
match n, k with
| _, 0 -> Set.empty.Add(Set.empty)
| 0, _ -> Set.empty
| n, k -> Set.union (Set.map (fun s -> Set.add n s) (allSubsets (n-1) (k-1)))
(allSubsets (n-1) k)
You can try it in the F# REPL:
> allSubsets 3 2;;
val it : Set<Set<int>> = set [set [1; 2]; set [1; 3]; set [2; 3]]
> allSubsets 4 2;;
val it : Set<Set<int>> = set [set [1; 2]; set [1; 3]; set [1; 4]; set [2; 3]; set [2; 4]; set [3; 4]]
This Java class implements the same algorithm:
import java.util.HashSet;
import java.util.Set;
public class AllSubsets {
public static Set<Set<Integer>> allSubsets(int setSize, int subsetSize) {
if (subsetSize == 0) {
HashSet<Set<Integer>> result = new HashSet<>();
result.add(new HashSet<>());
return result;
}
if (setSize == 0) {
return new HashSet<>();
}
Set<Set<Integer>> sets1 = allSubsets((setSize - 1), (subsetSize - 1));
for (Set<Integer> set : sets1) {
set.add(setSize);
}
Set<Set<Integer>> sets2 = allSubsets((setSize - 1), subsetSize);
sets1.addAll(sets2);
return sets1;
}
}
If you do not like F# or Java then visit this website. It lists solutions to your particular problem in various programming languages:
http://rosettacode.org/wiki/Combinations
JavaScript implementation:
var subsetArray = (function() {
return {
getResult: getResult
}
function getResult(array, n) {
function isBigEnough(value) {
return value.length === n;
}
var ps = [
[]
];
for (var i = 0; i < array.length; i++) {
for (var j = 0, len = ps.length; j < len; j++) {
ps.push(ps[j].concat(array[i]));
}
}
return ps.filter(isBigEnough);
}
})();
var arr = [1, 2, 3, 4,5,6,7,8,9];
console.log(subsetArray.getResult(arr,2));
Here is an iterative version in python. Essence of it is increment_counters() function which returns all possible combinations. We know it needs to be called C(n,r) times.
def nchooser(n,r):
"""Calculate the n choose r manual way"""
import math
f = math.factorial
return f(n) / f(n-r) / f(r)
def increment_counters(rc,r,n):
"""This is the essense of the algorithm. It generates all possible indexes.
Ex: for n = 4, r = 2, rc will have values (0,1),(0,2),(0,3),(1,2),(1,3),(2,3).
You may have better understanding if you print all possible 35 values for
n = 7, r = 3."""
rc[r-1] += 1 # first increment the least significant counter
if rc[r-1] < n: # if it does not overflow, return
return
# overflow at the last counter may cause some of previous counters to overflow
# find where it stops (ex: in n=7,r=3 case, 1,2,3 will follow 0,5,6)
for i in range(r-2,-1,-1): # from r-2 to 0 inclusive
if rc[i] < i+n-r:
break
# we found that rc[i] will not overflow. So, increment it and reset the
# counters right to it.
rc[i] += 1
for j in range(i+1,r):
rc[j] = rc[j-1] + 1
def combinations(lst, r):
"""Return all different sub-lists of size r"""
n = len(lst)
rc = [ i for i in range(r) ] # initialize counters
res = []
for i in range(nchooser(n,r)): # increment the counters max possible times
res.append(tuple(map(lambda k: lst[k],rc)))
increment_counters(rc,r,n)
return res
Here is a Java version of what I think Simple is talking about, using a binary representation of all sets in the power set. It's similar to how Abhiroop Sarkar did it, but I think a boolean array makes more sense than a string when you are just representing binary values.
private ArrayList<ArrayList<Object>> getSubsets(int m, Object[] objects){
// m = size of subset, objects = superset of objects
ArrayList<ArrayList<Object>> subsets = new ArrayList<>();
ArrayList<Integer> pot = new ArrayList<>();
int n = objects.length;
int p = 1;
if(m==0)
return subsets;
for(int i=0; i<=n; i++){
pot.add(p);
p*=2;
}
for(int i=1; i<p; i++){
boolean[] binArray = new boolean[n];
Arrays.fill(binArray, false);
int y = i;
int sum = 0;
for(int j = n-1; j>=0; j--){
int currentPot = pot.get(j);
if(y >= currentPot){
binArray[j] = true;
y -= currentPot;
sum++;
}
if(y<=0)
break;
}
if(sum==m){
ArrayList<Object> subsubset = new ArrayList<>();
for(int j=0; j < n; j++){
if(binArray[j]){
subsubset.add(objects[j]);
}
}
subsets.add(subsubset);
}
}
return subsets;
}
If you are looking for Iterator pattern answer then here you go.
public static <T> Iterable<List<T>> getList(final Iterable<? extends T> list) {
List<List<T>> listOfList = new ArrayList<>();
for (T t: list)
listOfList.add(Collections.singletonList(t));
return listOfList;
}
public static <T> Iterable<List<T>> getIterable(final Iterable<? extends T> list, final int size) {
final List<T> vals = new ArrayList<>();
int numElements = 0;
for (T t : list) {
vals.add(t);
numElements++;
}
if (size == 1) {
return getList(vals);
}
if (size == numElements) {
return Collections.singletonList(vals);
}
return new Iterable<List<T>>() {
#Override
public Iterator<List<T>> iterator() {
return new Iterator<List<T>>() {
int currPos = 0;
Iterator<List<T>> nextIterator = getIterable(
vals.subList(this.currPos + 1, vals.size()), size - 1).iterator();
#Override
public boolean hasNext() {
if ((this.currPos < vals.size()-2) && (this.currPos+size < vals.size()))
return true;
return false;
}
#Override
public List<T> next() {
if (!nextIterator.hasNext()) {
this.currPos++;
nextIterator = getIterable(vals.subList(this.currPos+1, vals.size()), size-1).iterator();
}
final List<T> ret = new ArrayList<>(nextIterator.next());
ret.add(0, vals.get(this.currPos));
return ret;
}
};
}
};
}
Here's a short python algorithm. I haven't used any predefined functions as such so I believe it could be easily translated to Java/C
def subs(l,n):
if(len(l)<k):
return []
elif(k==0):
return [[]]
else:
lis=[[l[0]]+b for b in (subs(l[1:],k-1))]
return (lis+subs(l[1:],k))
Here l is the list [1,2,...,m]
Here is a simple algorithm to enumerate all k-subsets of [n]={0,...,n-1} in lexicographic order. That is, the first of these subsets is S0=(0,1,2...,k-1), and the last is Slast=(n-k, n-k+1,...,n-1). For any k-subset S and for any 0 < j < k, we have S[j-1] < S[j] <= n+j-k.
For example, if n=10 and k=4, S0=(0,1,2,3) and Slast=(6,7,8,9). Notice, for example, that no combination can have S[1]>7 (in which case we'd have S[j]>n+j-k), since then there would be not enough values left to fill thr remaining positions j=2..3.
The idea of the algorithm is to start with the first combination S0, and then call next() repeatedly to generate the next k-subset each time. The function next() traverses the current k-subset backwards, starting from the last position j=k-1 down to 0, until it finds an entry S[j] that has not yet reached its maximum allowed value n+j-k and can thus be increased. Then it increases this position by one and fills the remaining positions, j+1..k-1 with consecutive values from S[j]+1. The algorithm stops as soon as no position can be further increased.
For example, suppose we have S=(3,7,8,9). Starting from j=3, we see that S[3],S[2],S[1] have reached their maximum values. Thus, the rightmost position that can still be increased is S[0]. This value is updated to S[0]+1=4, and the following positions are updated to 5,6,7. Hence the next k-subset will be S=(4,5,6,7).
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
bool next(int *S, int k, int n) {
int j = k-1;
while (j >= 0 && S[j] == n + j - k)
j--;
if (j < 0) return false;
S[j] += 1;
for (int i = j+1; i < k ; i++)
S[i] = S[i-1] + 1;
return true;
}
int main(int argc, char *argv[])
{
int n = 10;
int k = 4;
int *S = (int *)calloc(k, sizeof(int));
for (int j = 0; j < k; S[++j] = j); //first k-subset
int no = 0;
do {
printf("subset #%d: ",no++);
for (int j=0; j < k; j++) {
printf("%d ", S[j]);
}
printf("\n");
} while(next(S, k, n));
return 0;
}
This is a Facebook interview question I came across at an online portal.
Given a set S, find all the maximal subsets whose sum <= k. For example, if S = {1, 2, 3, 4, 5} and k = 7
Output is: {1, 2, 3} {1, 2, 4} {1, 5} {2, 5} {3, 4}
Hints:
Output doesn't contain any set which is a subset of other.
If X = {1, 2, 3} is one of the solution then all the subsets of X {1} {2} {3} {1, 2} {1, 3} {2, 3} are omitted.
Lexicographic ordering may be used to solve it.
Any ideas how could this be solved?
I have some idea - you need a tree.
If you have given input of {1, 2, 3, 4, 5}, and you're searching for maximal subsets - you should build a tree starting from the biggest numbers, and allways expand while sum <= k (so don't stop on 4-2, but go down to 1 to get 4-2-1).
So, nodes starting from 5 would be: 5-1 / 5-2 - only those 2 have sum <= 7
starting from 4: 4-3 / 4-2-1 / 4-1 (subset of previous)
starting from 3: 3-2-1 / 3-1 (subset of previous)
starting from 2: 2-1 (subset of 3-2-1)
starting from 1: 1 (subset of 2-1)
Then you can sort valid outputs and get {1, 2, 3} {1, 2, 4} {1, 5} {2, 5} {3, 4}
I know it's late to answer, but I think I've found a simple solution for this problem. We enumerate subsets of S in lexicographical order using backtracking and check the sum of subset generated so far.
When the sum exceeds k, the interesting part comes: we need to check if the generated subset is a proper subset of previously reported items.
One solution is to keep all the reported subsets and check for inclusion, but it's wasteful.
Instead, we calculate the difference between the k and the sum. If there is an element e in S such that e not in subset and e <= (k - sum), then the set we generated is a proper subset of a previously reported subset, and we can safely skip it.
Here is the complete working program in plain old C++, demonstrating the idea:
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
typedef std::set<int> Set;
typedef std::vector<int> SubSet;
bool seen_before(const Set &universe, const SubSet &subset, int diff) {
Set::const_iterator i = std::mismatch(universe.begin(), universe.end(),
subset.begin()).first;
return i != universe.end() && *i <= diff;
}
void process(const SubSet &subset) {
if (subset.empty()) {
std::cout << "{}\n";
return;
}
std::cout << "{" << subset.front();
for (SubSet::const_iterator i = subset.begin() + 1, e = subset.end();
i != e; ++i) {
std::cout << ", " << *i;
}
std::cout << "}\n";
}
void generate_max_subsets_rec(const Set &universe, SubSet &subset,
long sum, long k) {
Set::const_iterator i = subset.empty()
? universe.begin()
: universe.upper_bound(subset.back()),
e = universe.end();
if (i == e) {
if (!seen_before(universe, subset, k - sum))
process(subset);
return;
}
for (; i != e; ++i) {
long new_sum = sum + *i;
if (new_sum > k) {
if (!seen_before(universe, subset, int(k - sum)))
process(subset);
return;
} else {
subset.push_back(*i);
if (new_sum == k)
process(subset);
else
generate_max_subsets_rec(universe, subset, new_sum, k);
subset.pop_back();
}
}
}
void generate_max_subsets(const Set &universe, long k) {
SubSet subset;
subset.reserve(universe.size());
generate_max_subsets_rec(universe, subset, 0, k);
}
int main() {
int items[] = {1, 2, 3, 4, 5};
Set u(items, items + (sizeof items / sizeof items[0]));
generate_max_subsets(u, 7);
return 0;
}
The output is all maximum subsets in lexicographical order, one per line:
{1, 2, 3}
{1, 2, 4}
{1, 5}
{2, 5}
{3, 4}
This is a powerset problem. Recently I found this website about algorithms and it's been painting my imagination: hence the powerset/combinations solution following. You can simply copy, paste, and run the program.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Solution {
public static void maximalSubset
(int sum, int[] set, int choose,List<Integer[]> exclusion) {
if(1>choose) return;
int combinationSize = combinationSize(set.length,choose);
int index[]=new int[choose];
Integer subSet[] = new Integer[choose];
for(int i=0; i<choose;i++)
index[i]=i;
for(int i=0; i<combinationSize; i++) {
if(i!=0)
nextCombination(index,set.length);
for(int x=0; x<choose; x++)
subSet[x]=set[index[x]];
if(summation(sum,subSet) && !excluded(subSet,exclusion)) {
System.out.println(Arrays.toString(subSet));
exclusion.add(Arrays.copyOf(subSet,subSet.length));
}
}
maximalSubset(sum,set,choose-1,exclusion);
}//
private static int combinationSize(int n, int r) {
int den,limit;
if(r>n-r) {
den=n-r;
limit=r;
}else {
den=r;
limit=n-r;
}
long result=1;
for(int i=n; i>limit;i--)
result*=i;
for(int i=2; i<=den;i++)
result/=i;
return (int)result;
}//
private static void nextCombination(int[] A, int n) {
int c=A.length;
int i=c-1;
while(n-c+i==A[i])
i--;
A[i]++;
for(int j=i; j<c; j++)
A[j]=A[i]+j-i;
}//
private static boolean summation(int sum, Integer[] S) {
for(int i:S)
sum-=i;
return sum>=0;
}//
private static boolean excluded(Integer[] needle,List<Integer[]> haystack) {
for(Integer[] H: haystack) {
int count=0;
for(int h: H)
for(int n:needle)
if(h==n) {
count++;
break;//it's a set
}
if(count==needle.length)
return true;
}
return false;
}//
public static void main(String[] args) {
int[] S = {1, 2, 3, 4, 5};
int k = 7;
List<Integer[]> exclusion = new ArrayList<Integer[]>();
maximalSubset(k,S,S.length,exclusion);
}
}
An old question but still an interesting one.
Here's a recursive Java 8 solution, with a "permutational" approach.
Optimized for cleaner and shorter code rather than performance -- for example the sorting and pruning would only need to take place once.
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import java.util.*;
import java.util.stream.Collectors;
public class SubsetFinder {
public List<List<Integer>> findSubsets(List<Integer> input, int k) {
List<List<Integer>> listOfLists = new ArrayList<>();
List<Integer> copy = Ordering.natural().sortedCopy(input);
while (!copy.isEmpty()) {
int v = copy.remove(copy.size() - 1);
if (v == k || (copy.isEmpty() && v <= k)) {
// No need to look for subsets if the element itself == k, or
// if it's the last remaining element and <= k.
listOfLists.add(new ArrayList<>(Arrays.asList(v)));
} else if (v < k) {
findSubsets(copy, k - v).forEach(subList -> {
subList.add(v);
listOfLists.add(subList);
});
}
}
// Prune sets which are duplicates or subsets of other sets
return listOfLists.stream().filter(
candidate -> listOfLists.stream().noneMatch(
lol -> candidate != lol && lol.containsAll(candidate)
)
).collect(Collectors.toList());
}
}
To test it:
public static void main(String[] args) {
new SubsetFinder()
.findSubsets(ImmutableList.of(1, 2, 3, 4, 5), 7)
.forEach(System.out::println);
}
Algorithm is the following:
Starting from empty subSet.
Cycle through original array from the beginning (assuming array is already sorted in ascending order) until currentSum is less or equal target sum.
If current element added to currentSum is less than target sum, adding to current subSet current element and running recursion starting from the next element.
Breaking current cycle if current sum exceed targetSum.
If we can't add more elements into current subSet, we checking if it is maximal and print it in this case.
To determine maximal subSets we can compare original array and current subSet element by element, searching for the first mismatch. If element at first mismatch index is greater than difference between currentSum and targetSum, subSet is maximal and should be printed.
Working solution on Java is below:
public class Test {
/**
* Assuming alphabet[] is already sorted in increasing order
*/
public static void printMaximalSubSetsToSum(int[] alphabet, int sum) {
if (alphabet == null || alphabet.length == 0) {
return;
}
if (alphabet[0] > sum) {
// no sense to search, since smallest element in array already bigger than sum
return;
} else if (alphabet[0] == sum) {
Set<Integer> subSet = new HashSet<>();
subSet.add(alphabet[0]);
printSubset(subSet);
}
Set<Integer> subSet = new HashSet<>();
processMaximalSubSetToSum(alphabet, sum, 0, 0, subSet);
}
private static void processMaximalSubSetToSum(int[] alphabet, int sum, int sumSoFar, int startFrom, Set<Integer> subSet) {
if (startFrom >= alphabet.length) {
if (isMaximalSubSet(alphabet, subSet, sum - sumSoFar)) {
printSubset(subSet);
}
return;
}
for (int i = startFrom; i < alphabet.length; i++) {
int newSum = sumSoFar + alphabet[i];
if (newSum > sum) {
if (isMaximalSubSet(alphabet, subSet, sum - sumSoFar)) {
printSubset(subSet);
}
return;
} else {
subSet.add(alphabet[i]);
if (newSum == sum) {
printSubset(subSet);
} else {
processMaximalSubSetToSum(alphabet, sum, newSum, i + 1, subSet);
}
subSet.remove(alphabet[i]);
}
}
}
private static boolean isMaximalSubSet(int[] alphabet, Set<Integer> subSet, int diff) {
// search first mismatch element between alphabet and current SubSet
Iterator<Integer> it = subSet.iterator();
int i = 0;
while (it.hasNext()) {
if (it.next() != alphabet[i]) {
break;
}
i++;
}
return i >= alphabet.length || alphabet[i] > diff;
}
private static void printSubset(Set<Integer> subset) {
System.out.println(subset);
}
public static void main(String[] args) throws java.lang.Exception {
//printMaximalSubSetsToSum(new int[]{1, 2, 3, 4, 5}, 7);
// Correct output is: {1, 2, 3}; {1, 2, 4}; {1, 5}; {2, 5}; {3, 4}
}
}
I am sorry for chipping in so late. But how about doing this?
1) Build a MIN-HEAP structure from the given array/set
2) traverse the structure from the root and keep subtracting the value at the node that you visit. Once you exceed the required sum (curr_sum > k), output this path, backtrack to the parent and take another path (this can be done recursively).
3) If backtracking takes you back to the original node that you started from, implement the entire algorithm recursively from root->left node.
4) Do the same two steps (2) and (3) above but with a MAX-HEAP now.
I am new to algorithms and data structures, and have only started reading Intro to Algos-Cormen. This might be a faulty solution, but I would be more than happy if anyone points out the fault to me :)