Calculating all of the subsets of a set of numbers - java

I want to find the subsets of a set of integers. It is the first step of "Sum of Subsets" algorithm with backtracking. I have written the following code, but it doesn't return the correct answer:
BTSum(0, nums);
///**************
ArrayList<Integer> list = new ArrayList<Integer>();
public static ArrayList<Integer> BTSum(int n, ArrayList<Integer> numbers) {
if (n == numbers.size()) {
for (Integer integer : list) {
System.out.print(integer+", ");
}
System.out.println("********************");
list.removeAll(list);
System.out.println();
} else {
for (int i = n; i < numbers.size(); i++) {
if (i == numbers.size() - 1) {
list.add(numbers.get(i));
BTSum(i + 1, numbers);
} else {
list.add(numbers.get(i));
for (int j = i+1; j < numbers.size(); j++)
BTSum(j, numbers);
}
}
}
return null;
}
For example, if I want to calculate the subsets of set = {1, 3, 5}
The result of my method is:
1, 3, 5, ********************
5, ********************
3, 5, ********************
5, ********************
3, 5, ********************
5, ********************
I want it to produce:
1, 3, 5
1, 5
3, 5
5
I think the problem is from the part
list.removeAll(list);
but I dont know how to correct it.

What you want is called a Powerset. Here is a simple implementation of it:
public static Set<Set<Integer>> powerSet(Set<Integer> originalSet) {
Set<Set<Integer>> sets = new HashSet<Set<Integer>>();
if (originalSet.isEmpty()) {
sets.add(new HashSet<Integer>());
return sets;
}
List<Integer> list = new ArrayList<Integer>(originalSet);
Integer head = list.get(0);
Set<Integer> rest = new HashSet<Integer>(list.subList(1, list.size()));
for (Set<Integer> set : powerSet(rest)) {
Set<Integer> newSet = new HashSet<Integer>();
newSet.add(head);
newSet.addAll(set);
sets.add(newSet);
sets.add(set);
}
return sets;
}
I will give you an example to explain how the algorithm works for the powerset of {1, 2, 3}:
Remove {1}, and execute powerset for {2, 3};
Remove {2}, and execute powerset for {3};
Remove {3}, and execute powerset for {};
Powerset of {} is {{}};
Powerset of {3} is 3 combined with {{}} = { {}, {3} };
Powerset of {2, 3} is {2} combined with { {}, {3} } = { {}, {3}, {2}, {2, 3} };
Powerset of {1, 2, 3} is {1} combined with { {}, {3}, {2}, {2, 3} } = { {}, {3}, {2}, {2, 3}, {1}, {3, 1}, {2, 1}, {2, 3, 1} }.

Just a primer how you could solve the problem:
Approach 1
Take the first element of your number list
generate all subsets from the remaining number list (i.e. the number list without the chosen one) => Recursion!
for every subset found in the previous step, add the subset itself and the subset joined with the element chosen in step 1 to the output.
Of course, you have to check the base case, i.e. if your number list is empty.
Approach 2
It is a well known fact that a set with n elements has 2^n subsets. Thus, you can count in binary from 0 to 2^n and interpret the binary number as the corresponding subset. Note that this approach requires a binary number with a sufficient amount of digits to represent the whole set.
It should be a not too big problem to convert one of the two approaches into code.

Your code is really confusing and there is no explanation.
You can do iteratively with a bitmask that determines which numbers are in the set. Each number from 0 to 2^n gives a unique subset in its binary representation, for example
for n = 3:
i = 5 -> 101 in binary, choose first and last elements
i = 7 -> 111 in binary, choose first 3 elements
Suppose there are n elements (n < 64, after all if n is larger than 64 you'll run that forever).
for(long i = 0; i < (1<<n); i++){
ArrayList<Integer> subset = new ArrayList<Integer>();
for(int j = 0; j < n; j++){
if((i>>j) & 1) == 1){ // bit j is on
subset.add(numbers.get(j));
}
}
// print subset
}

Considering a Noob Visitor (thanks to google) to this question - like me
Here is a recursive solution which works on simple principal :
Set = {a,b,c,d,e}
then we can break it to {a} + Subset of {b,c,d,e}
public class Powerset{
String str = "abcd"; //our string
public static void main(String []args){
Powerset ps = new Powerset();
for(int i = 0; i< ps.str.length();i++){ //traverse through all characters
ps.subs("",i);
}
}
void subs(String substr,int index)
{
String s = ""+str.charAt(index); //very important, create a variable on each stack
s = substr+s; //append the subset so far
System.out.println(s); //print
for(int i=index+1;i<str.length();i++)
subs(s,i); //call recursively
}
}
OUTPUT
a
ab
abc
abcd
abd
ac
acd
ad
b
bc
bcd
bd
c
cd
d

It is clear that, the total number of subsets of any given set is equal to 2^(number of elements in the set). If set
A = {1, 2, 3}
then subset of A is:
{ }, { 1 }, { 2 }, { 3 }, { 1, 2 }, { 1, 3 }, { 2, 3 }, { 1, 2, 3 }
If we look it is like binary numbers.
{ 000 }, { 001 }, { 010 }, { 011 }, { 100 }, { 101 }, { 110 }, { 111 }
If we take into account above:
static void subSet(char[] set) {
int c = set.length;
for (int i = 0; i < (1 << c); i++) {
System.out.print("{");
for (int j = 0; j < c; j++) {
if ((i & (1 << j)) > 0) {
System.out.print(set[j] + " ");
}
}
System.out.println("}");
}
}
public static void main(String[] args) {
char c[] = {'a', 'b', 'c'};
subSet(c);
}

private static void findSubsets(int array[])
{
int numOfSubsets = 1 << array.length;
for(int i = 0; i < numOfSubsets; i++)
{
int pos = array.length - 1;
int bitmask = i;
System.out.print("{");
while(bitmask > 0)
{
if((bitmask & 1) == 1)
System.out.print(array[pos]+",");
bitmask >>= 1;
pos--;
}
System.out.print("}");
}
}

Based on what I learnt today, here is the Java Solution
It is based on recursion
public class Powerset {
public static void main(String[] args) {
final List<List<String>> allSubsets = powerSet(Arrays.asList(1, 2, 3, 4), 0);
for (List<String> subsets : allSubsets) {
System.out.println(subsets);
}
}
private static List<List<String>> powerSet(final List<Integer> values,
int index) {
if (index == values.size()) {
return new ArrayList<>();
}
int val = values.get(index);
List<List<String>> subset = powerSet(values, index + 1);
List<List<String>> returnList = new ArrayList<>();
returnList.add(Arrays.asList(String.valueOf(val)));
returnList.addAll(subset);
for (final List<String> subsetValues : subset) {
for (final String subsetValue : subsetValues) {
returnList.add(Arrays.asList(val + "," + subsetValue));
}
}
return returnList;
}
}
Running it will give results as
[1]
[2]
[3]
[4]
[3,4]
[2,3]
[2,4]
[2,3,4]
[1,2]
[1,3]
[1,4]
[1,3,4]
[1,2,3]
[1,2,4]
[1,2,3,4]

public static void printSubsets(int[] arr) {
for (int start = 0; start < arr.length; start++) { // iterate through each element of the array
for (int i = 0; i < arr.length - start; i++) { // find number of subsets for the element
int[] tmp = new int[i + 1]; // calculate a temporal array size
for (int j = 0; j < tmp.length; j++) { // populate the array with corresponding elements
tmp[j] = arr[start + j];
}
System.out.println(Arrays.toString(tmp));
}
}
}

I was actually trying to solve this one and got the algorithm #phimuemue on the previous post .Here is what I implemented. Hope this works.
/**
*#Sherin Syriac
*
*/
import java.util.ArrayList;
import java.util.List;
public class SubSet {
ArrayList<List<Integer>> allSubset = new ArrayList<List<Integer>>();
/**
* #param args
*/
public static void main(String[] args) {
SubSet subSet = new SubSet();
ArrayList<Integer> set = new ArrayList<Integer>();
set.add(1);
set.add(2);
set.add(3);
set.add(4);
subSet.getSubSet(set, 0);
for (List<Integer> list : subSet.allSubset) {
System.out.print("{");
for (Integer element : list) {
System.out.print(element);
}
System.out.println("}");
}
}
public void getSubSet(ArrayList<Integer> set, int index) {
if (set.size() == index) {
ArrayList<Integer> temp = new ArrayList<Integer>();
allSubset.add(temp);
} else {
getSubSet(set, index + 1);
ArrayList<List<Integer>> tempAllSubsets = new ArrayList<List<Integer>>();
for (List subset : allSubset) {
ArrayList<Integer> newList = new ArrayList<Integer>();
newList.addAll(subset);
newList.add(set.get(index));
tempAllSubsets.add(newList);
}
allSubset.addAll(tempAllSubsets);
}
}
}

// subsets for the set of 5,9,8
import java.util.ArrayList;
import java.util.List;
public class Subset {
public static void main(String[] args) {
List<Integer> s = new ArrayList<Integer>();
s.add(9);
s.add(5);
s.add(8);
int setSize = s.size();
int finalValue = (int) (Math.pow(2, setSize));
String bValue = "";
for (int i = 0; i < finalValue; i++) {
bValue = Integer.toBinaryString(i);
int bValueSize = bValue.length();
for (int k = 0; k < (setSize - bValueSize); k++) {
bValue = "0" + bValue;
}
System.out.print("{ ");
for (int j = 0; j < setSize; j++) {
if (bValue.charAt(j) == '1') {
System.out.print((s.get(j)) + " ");
}
}
System.out.print("} ");
}
}
}
//Output : { } { 8 } { 5 } { 5 8 } { 9 } { 9 8 } { 9 5 } { 9 5 8 }

public static ArrayList<ArrayList<Integer>> powerSet(List<Integer> intList) {
ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
result.add(new ArrayList<Integer>());
for (int i : intList) {
ArrayList<ArrayList<Integer>> temp = new ArrayList<ArrayList<Integer>>();
for (ArrayList<Integer> innerList : result) {
innerList = new ArrayList<Integer>(innerList);
innerList.add(i);
temp.add(innerList);
}
result.addAll(temp);
}
return result;
}

If you're dealing with a large collection of elements, you may (though not likely) run into issues with stack overflow. I admit you're more likely to run out of memory before you overflow the stack, but I will put this non-recursive method here anyway.
public static final <T> Set<Set<T>> powerSet(final Iterable<T> original) {
Set<Set<T>> sets = new HashSet<>();
sets.add(new HashSet<>());
for (final T value : original) {
final Set<Set<T>> newSets = new HashSet<>(sets);
for (final Set<T> set : sets) {
final Set<T> newSet = new HashSet<>(set);
newSet.add(value);
newSets.add(newSet);
}
sets = newSets;
}
return sets;
}
Or if you'd rather deal with arrays:
#SuppressWarnings("unchecked")
public static final <T> T[][] powerSet(final T... original) {
T[][] sets = (T[][]) Array.newInstance(original.getClass(), 1);
sets[0] = Arrays.copyOf(original, 0);
for (final T value : original) {
final int oldLength = sets.length;
sets = Arrays.copyOf(sets, oldLength * 2);
for (int i = 0; i < oldLength; i++) {
final T[] oldArray = sets[i];
final T[] newArray = Arrays.copyOf(oldArray, oldArray.length + 1);
newArray[oldArray.length] = value;
sets[i + oldLength] = newArray;
}
}
return sets;
}

Simple Java recursive solution -
private static List<List<Integer>> allsubSet(List<Integer> integers, int start, int end) {
//Base case if there is only one element so there would be two subset
// empty list and that element
if(start == end) {
List<List<Integer>> result = new ArrayList<>();
List<Integer> emptyList = new ArrayList<>();
result.add(emptyList);
List<Integer> element = new ArrayList<>();
element.add(integers.get(start));
result.add(element );
return result;
}
//I know if by recursion we can expect that we'll get the n-1 correct result
List<List<Integer>> lists = allsubSet(integers, start, end-1);
//here i copy all the n-1 results and just added the nth element in expected results
List<List<Integer>> copyList = new ArrayList<>(lists);
for (List<Integer> list : lists) {
List<Integer> copy= new ArrayList<>(list);
copy.add(integers.get(end));
copyList.add(copy);
}
return copyList;
}
To avoid redundancy we can simply use Set in place of List

Get all subset using recursion (on similar lines for solving permutations from the book : Thinking recursively with Java)
public class ChapterSix {
public static void main(String[] args) {
new ChapterSix().listSubSets("", "123");
}
void listSubSets(String prefix, String s) {
System.out.println(prefix);
if("".equals(s)) {
return;
} else {
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
String rest = s.substring(i + 1);
listSubSets(prefix + ch, rest);
}
}
}
}
Output:
1
12
123
13
2
23
3

Here's some pseudocode. You can cut same recursive calls by storing the values for each call as you go and before recursive call checking if the call value is already present.
The following algorithm will have all the subsets excluding the empty set.
list * subsets(string s, list * v){
if(s.length() == 1){
list.add(s);
return v;
}
else
{
list * temp = subsets(s[1 to length-1], v);
int length = temp->size();
for(int i=0;i<length;i++){
temp.add(s[0]+temp[i]);
}
list.add(s[0]);
return temp;
}
}

Here's the logic to print all the subsets of a given set of numbers. This is also called powerset of a set. I have used a simple recursive approach to solve this using Java, but you can correspondingly code in other languages as well.
import java.util.Scanner;
public class PowerSubset {
public static void main(String[] args) {
// HardCoded Input
int arr[] = { 1, 2, 3 };//original array whose subset is to be found
int n=3; //size of array
// Dynamic Input
/*Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}*/
int data[] = new int[arr.length]; // temporary array
printSubset(arr, data, n, 0, 0);
}
public static void printSubset(int arr[], int data[], int n, int dataIndex, int arrIndex) {
if (arrIndex == n) { //comparing with n since now you are at the leaf node
System.out.print("[");//watch pictorial chart in the below video link
for (int j = 0; j < n; j++) {
System.out.print(data[j] == 0 ? "" : data[j]);
}
System.out.print("]");
System.out.println();
return;
}
data[dataIndex] = arr[arrIndex];
printSubset(arr, data, n, dataIndex + 1, arrIndex + 1);//recursive call 1
data[dataIndex] = 0;
printSubset(arr, data, n, dataIndex, arrIndex + 1);//recursive call 2
}
}
Output of the above code:
[123]
[12]
[13]
[1]
[23]
[2]
[3]
[]

Related

How to find in Java the largest value in variable length List with variable length nested Lists index by index?

I have a List<List<Integer>> that has an arbitrary number of variable length List<Integer>. I need to compare each value at the same index and make sure those values are sorted meaning the first list should be smaller than the next based on index by index values.
In the below example, each index would be compared between the lists at index i = 0, the values are all int 5 so continue. For i = 1, the values are all 3, so continue. For i = 2, listA is larger because it has an additional integer where as the others are null and should return false.
List<List<Integer>> listOfLists = List.of(List.of(5, 3, 2), // A
List.of(5, 3), // B
List.of(5, 3)); // C
Another example. Here, these are not in the correct order because listB fails on the last index because ListA and listC have values as they are not null, so listB is smaller.
List<List<Integer>> listOfLists = List.of(List.of(4, 3, 2, 1), // A
List.of(4, 3, 2), // B
List.of(4, 3, 2, 1)); // C
In this example, they are in order.
List<List<Integer>> listOfLists = List.of(List.of(4, 3), // A
List.of(4, 3, 1), // B
List.of(5, 3, 2, 1), // C
List.of(5, 4, 3)); // D
I have tried many options. I have tried to use Comparator to create a custom compare method, nested for loops, recursion, etc. I keep running into problems with IndexOutOfBOundsExceptions and this is still kind of mind boggling for me. I have been able to sort the lists or find the maximum values of the lists and compare them to the others, but not while maintaining the order.
I feel like pushing each value at the same index onto a stack and then comparing them would be a good solution, but I am having trouble implementing it.
The end result is I need to determine if List<List<Integer>> is in proper order from smallest to largest and return true; otherwise, return false. The last example would be true and the others would be false.
EDIT
I came up with this and it seems to work.
public class ListTest {
public static void main(String... args) {
List<List<Integer>> listOfLists = List.of(List.of(3, 2, 1), // A
List.of(4, 3, 1), // B
List.of(5, 4, 3)); // C
boolean correctOrder = true;
int max = getMaxLength(listOfLists);
Stack<Integer> stack = new Stack<>();
for (int i = 0; i < max; i++) {
for (int j = 0; j < listOfLists.size(); j++) {
try {
stack.push(listOfLists.get(j).get(i));
} catch(IndexOutOfBoundsException ex) {
stack.push(0);
}
}
if (!isSorted(stack)) {
correctOrder = false;
break;
}
}
System.out.println(correctOrder);
}
public static boolean isSorted(Stack<Integer> stack) {
int temp = stack.pop();
while (!stack.isEmpty()) {
int compare = stack.pop();
if (temp < compare)
return false;
temp = compare;
}
return true;
}
public static int getMaxLength(List<List<Integer>> list) {
int maxLength = 0;
for (int i = 0; i < list.size(); i++) {
if (list.get(i).size() > maxLength) {
maxLength = list.get(i).size();
System.out.println(maxLength);
}
}
return maxLength;
}
}
So you need a comparator. This is pretty easy. Just create two separate comparators: first should sort lists by size, second - by content.
public static Comparator<List<Integer>> createComparator() {
Comparator<List<Integer>> sortBySizeAsc = Comparator.comparingInt(List::size);
Comparator<List<Integer>> sortByContentAsc = (one, two) -> {
Iterator<Integer> it1 = one.iterator();
Iterator<Integer> it2 = two.iterator();
while (it1.hasNext() && it2.hasNext()) {
int res = Integer.compare(it1.next(), it2.next());
if (res != 0)
return res;
}
return 0;
};
return sortBySizeAsc.thenComparing(sortByContentAsc);
}
You could sort a copy of your lists acording to your order definition and check if the copy and original are equal. (Might be not the efficient way to do if your list are very big).
static boolean areListsInOrder(List<List<Integer>> listOfLists){
//a comparator to sort your lists comparing each value index wise, then comparing by list size
Comparator<List<Integer>> comp = (list1,list2) -> IntStream.range(0, Math.min(list1.size(), list2.size()))
.map(i -> list1.get(i).compareTo(list2.get(i)))
.dropWhile( i -> i == 0).findFirst()
.orElse(Integer.compare(list1.size(), list2.size()));
//copy your list and sort
List<List<Integer>> copy = new ArrayList<>(listOfLists);
copy.sort(comp);
//check if the sorted and original are equal
return copy.equals(listOfLists);
}
As far as I have understood what you're trying to achieve, below should be the solution:
boolean checkListsOrder(List<List<Integer>> listOfLists) {
int maxSize = 0;
for (List<Integer> singleList : listOfLists)
maxSize = maxSize > singleList.size() ? maxSize : singleList.size();
Map<Integer, Integer> checkIfAllValuesEqualsAndWrongOrdered = new HashMap<>();
for (int i = 0; i < listOfLists.size(); i++)
checkIfAllValuesEqualsAndWrongOrdered.put(i, 0);
for (int j = 0; j < maxSize; j++) {
TreeMap<Integer, Integer> orderOfValues = new TreeMap<>();
for (int i = 0; i < listOfLists.size(); i++) {
if (j < listOfLists.get(i).size()) {
orderOfValues.put(i, listOfLists.get(i).get(j));
}
}
Map.Entry<Integer, Integer> previousEntry = orderOfValues.firstEntry();
Map.Entry<Integer, Integer> nextEntry = orderOfValues.higherEntry(previousEntry.getKey());
while (nextEntry != null) {
if (previousEntry.getValue() > nextEntry.getValue())
return false;
else if (previousEntry.getValue() == nextEntry.getValue() && listOfLists.get(previousEntry.getKey()).size() > listOfLists.get(nextEntry.getKey()).size()) {
if (checkIfAllValuesEqualsAndWrongOrdered.get(nextEntry.getKey()) + 1 == listOfLists.get(nextEntry.getKey()).size() - 1)
return false;
else
checkIfAllValuesEqualsAndWrongOrdered.put(nextEntry.getKey(), checkIfAllValuesEqualsAndWrongOrdered.get(nextEntry.getKey()) + 1);
}
previousEntry = nextEntry;
nextEntry = orderOfValues.higherEntry(nextEntry.getKey());
}
}
return true;
}

Get all unique sequences from an array [duplicate]

For example I have this array:
int a[] = new int[]{3,4,6,2,1};
I need list of all permutations such that if one is like this, {3,2,1,4,6}, others must not be the same. I know that if the length of the array is n then there are n! possible combinations. How can this algorithm be written?
Update: thanks, but I need a pseudo code algorithm like:
for(int i=0;i<a.length;i++){
// code here
}
Just algorithm. Yes, API functions are good, but it does not help me too much.
Here is how you can print all permutations in 10 lines of code:
public class Permute{
static void permute(java.util.List<Integer> arr, int k){
for(int i = k; i < arr.size(); i++){
java.util.Collections.swap(arr, i, k);
permute(arr, k+1);
java.util.Collections.swap(arr, k, i);
}
if (k == arr.size() -1){
System.out.println(java.util.Arrays.toString(arr.toArray()));
}
}
public static void main(String[] args){
Permute.permute(java.util.Arrays.asList(3,4,6,2,1), 0);
}
}
You take first element of an array (k=0) and exchange it with any element (i) of the array. Then you recursively apply permutation on array starting with second element. This way you get all permutations starting with i-th element. The tricky part is that after recursive call you must swap i-th element with first element back, otherwise you could get repeated values at the first spot. By swapping it back we restore order of elements (basically you do backtracking).
Iterators and Extension to the case of repeated values
The drawback of previous algorithm is that it is recursive, and does not play nicely with iterators. Another issue is that if you allow repeated elements in your input, then it won't work as is.
For example, given input [3,3,4,4] all possible permutations (without repetitions) are
[3, 3, 4, 4]
[3, 4, 3, 4]
[3, 4, 4, 3]
[4, 3, 3, 4]
[4, 3, 4, 3]
[4, 4, 3, 3]
(if you simply apply permute function from above you will get [3,3,4,4] four times, and this is not what you naturally want to see in this case; and the number of such permutations is 4!/(2!*2!)=6)
It is possible to modify the above algorithm to handle this case, but it won't look nice. Luckily, there is a better algorithm (I found it here) which handles repeated values and is not recursive.
First note, that permutation of array of any objects can be reduced to permutations of integers by enumerating them in any order.
To get permutations of an integer array, you start with an array sorted in ascending order. You 'goal' is to make it descending. To generate next permutation you are trying to find the first index from the bottom where sequence fails to be descending, and improves value in that index while switching order of the rest of the tail from descending to ascending in this case.
Here is the core of the algorithm:
//ind is an array of integers
for(int tail = ind.length - 1;tail > 0;tail--){
if (ind[tail - 1] < ind[tail]){//still increasing
//find last element which does not exceed ind[tail-1]
int s = ind.length - 1;
while(ind[tail-1] >= ind[s])
s--;
swap(ind, tail-1, s);
//reverse order of elements in the tail
for(int i = tail, j = ind.length - 1; i < j; i++, j--){
swap(ind, i, j);
}
break;
}
}
Here is the full code of iterator. Constructor accepts an array of objects, and maps them into an array of integers using HashMap.
import java.lang.reflect.Array;
import java.util.*;
class Permutations<E> implements Iterator<E[]>{
private E[] arr;
private int[] ind;
private boolean has_next;
public E[] output;//next() returns this array, make it public
Permutations(E[] arr){
this.arr = arr.clone();
ind = new int[arr.length];
//convert an array of any elements into array of integers - first occurrence is used to enumerate
Map<E, Integer> hm = new HashMap<E, Integer>();
for(int i = 0; i < arr.length; i++){
Integer n = hm.get(arr[i]);
if (n == null){
hm.put(arr[i], i);
n = i;
}
ind[i] = n.intValue();
}
Arrays.sort(ind);//start with ascending sequence of integers
//output = new E[arr.length]; <-- cannot do in Java with generics, so use reflection
output = (E[]) Array.newInstance(arr.getClass().getComponentType(), arr.length);
has_next = true;
}
public boolean hasNext() {
return has_next;
}
/**
* Computes next permutations. Same array instance is returned every time!
* #return
*/
public E[] next() {
if (!has_next)
throw new NoSuchElementException();
for(int i = 0; i < ind.length; i++){
output[i] = arr[ind[i]];
}
//get next permutation
has_next = false;
for(int tail = ind.length - 1;tail > 0;tail--){
if (ind[tail - 1] < ind[tail]){//still increasing
//find last element which does not exceed ind[tail-1]
int s = ind.length - 1;
while(ind[tail-1] >= ind[s])
s--;
swap(ind, tail-1, s);
//reverse order of elements in the tail
for(int i = tail, j = ind.length - 1; i < j; i++, j--){
swap(ind, i, j);
}
has_next = true;
break;
}
}
return output;
}
private void swap(int[] arr, int i, int j){
int t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
public void remove() {
}
}
Usage/test:
TCMath.Permutations<Integer> perm = new TCMath.Permutations<Integer>(new Integer[]{3,3,4,4,4,5,5});
int count = 0;
while(perm.hasNext()){
System.out.println(Arrays.toString(perm.next()));
count++;
}
System.out.println("total: " + count);
Prints out all 7!/(2!*3!*2!)=210 permutations.
If you're using C++, you can use std::next_permutation from the <algorithm> header file:
int a[] = {3,4,6,2,1};
int size = sizeof(a)/sizeof(a[0]);
std::sort(a, a+size);
do {
// print a's elements
} while(std::next_permutation(a, a+size));
Here is an implementation of the Permutation in Java:
Permutation - Java
You should have a check on it!
Edit: code pasted below to protect against link-death:
// Permute.java -- A class generating all permutations
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.lang.reflect.Array;
public class Permute implements Iterator {
private final int size;
private final Object [] elements; // copy of original 0 .. size-1
private final Object ar; // array for output, 0 .. size-1
private final int [] permutation; // perm of nums 1..size, perm[0]=0
private boolean next = true;
// int[], double[] array won't work :-(
public Permute (Object [] e) {
size = e.length;
elements = new Object [size]; // not suitable for primitives
System.arraycopy (e, 0, elements, 0, size);
ar = Array.newInstance (e.getClass().getComponentType(), size);
System.arraycopy (e, 0, ar, 0, size);
permutation = new int [size+1];
for (int i=0; i<size+1; i++) {
permutation [i]=i;
}
}
private void formNextPermutation () {
for (int i=0; i<size; i++) {
// i+1 because perm[0] always = 0
// perm[]-1 because the numbers 1..size are being permuted
Array.set (ar, i, elements[permutation[i+1]-1]);
}
}
public boolean hasNext() {
return next;
}
public void remove() throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
private void swap (final int i, final int j) {
final int x = permutation[i];
permutation[i] = permutation [j];
permutation[j] = x;
}
// does not throw NoSuchElement; it wraps around!
public Object next() throws NoSuchElementException {
formNextPermutation (); // copy original elements
int i = size-1;
while (permutation[i]>permutation[i+1]) i--;
if (i==0) {
next = false;
for (int j=0; j<size+1; j++) {
permutation [j]=j;
}
return ar;
}
int j = size;
while (permutation[i]>permutation[j]) j--;
swap (i,j);
int r = size;
int s = i+1;
while (r>s) { swap(r,s); r--; s++; }
return ar;
}
public String toString () {
final int n = Array.getLength(ar);
final StringBuffer sb = new StringBuffer ("[");
for (int j=0; j<n; j++) {
sb.append (Array.get(ar,j).toString());
if (j<n-1) sb.append (",");
}
sb.append("]");
return new String (sb);
}
public static void main (String [] args) {
for (Iterator i = new Permute(args); i.hasNext(); ) {
final String [] a = (String []) i.next();
System.out.println (i);
}
}
}
According to wiki https://en.wikipedia.org/wiki/Heap%27s_algorithm
Heap's algorithm generates all possible permutations of n objects. It was first proposed by B. R. Heap in 1963. The algorithm minimizes movement: it generates each permutation from the previous one by interchanging a single pair of elements; the other n−2 elements are not disturbed. In a 1977 review of permutation-generating algorithms, Robert Sedgewick concluded that it was at that time the most effective algorithm for generating permutations by computer.
So if we want to do it in recursive manner, Sudo code is bellow.
procedure generate(n : integer, A : array of any):
if n = 1 then
output(A)
else
for i := 0; i < n - 1; i += 1 do
generate(n - 1, A)
if n is even then
swap(A[i], A[n-1])
else
swap(A[0], A[n-1])
end if
end for
generate(n - 1, A)
end if
java code:
public static void printAllPermutations(
int n, int[] elements, char delimiter) {
if (n == 1) {
printArray(elements, delimiter);
} else {
for (int i = 0; i < n - 1; i++) {
printAllPermutations(n - 1, elements, delimiter);
if (n % 2 == 0) {
swap(elements, i, n - 1);
} else {
swap(elements, 0, n - 1);
}
}
printAllPermutations(n - 1, elements, delimiter);
}
}
private static void printArray(int[] input, char delimiter) {
int i = 0;
for (; i < input.length; i++) {
System.out.print(input[i]);
}
System.out.print(delimiter);
}
private static void swap(int[] input, int a, int b) {
int tmp = input[a];
input[a] = input[b];
input[b] = tmp;
}
public static void main(String[] args) {
int[] input = new int[]{0,1,2,3};
printAllPermutations(input.length, input, ',');
}
This a 2-permutation for a list wrapped in an iterator
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/* all permutations of two objects
*
* for ABC: AB AC BA BC CA CB
*
* */
public class ListPermutation<T> implements Iterator {
int index = 0;
int current = 0;
List<T> list;
public ListPermutation(List<T> e) {
list = e;
}
public boolean hasNext() {
return !(index == list.size() - 1 && current == list.size() - 1);
}
public List<T> next() {
if(current == index) {
current++;
}
if (current == list.size()) {
current = 0;
index++;
}
List<T> output = new LinkedList<T>();
output.add(list.get(index));
output.add(list.get(current));
current++;
return output;
}
public void remove() {
}
}
There are n! total permutations for the given array size n. Here is code written in Java using DFS.
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> results = new ArrayList<List<Integer>>();
if (nums == null || nums.length == 0) {
return results;
}
List<Integer> result = new ArrayList<>();
dfs(nums, results, result);
return results;
}
public void dfs(int[] nums, List<List<Integer>> results, List<Integer> result) {
if (nums.length == result.size()) {
List<Integer> temp = new ArrayList<>(result);
results.add(temp);
}
for (int i=0; i<nums.length; i++) {
if (!result.contains(nums[i])) {
result.add(nums[i]);
dfs(nums, results, result);
result.remove(result.size() - 1);
}
}
}
For input array [3,2,1,4,6], there are totally 5! = 120 possible permutations which are:
[[3,4,6,2,1],[3,4,6,1,2],[3,4,2,6,1],[3,4,2,1,6],[3,4,1,6,2],[3,4,1,2,6],[3,6,4,2,1],[3,6,4,1,2],[3,6,2,4,1],[3,6,2,1,4],[3,6,1,4,2],[3,6,1,2,4],[3,2,4,6,1],[3,2,4,1,6],[3,2,6,4,1],[3,2,6,1,4],[3,2,1,4,6],[3,2,1,6,4],[3,1,4,6,2],[3,1,4,2,6],[3,1,6,4,2],[3,1,6,2,4],[3,1,2,4,6],[3,1,2,6,4],[4,3,6,2,1],[4,3,6,1,2],[4,3,2,6,1],[4,3,2,1,6],[4,3,1,6,2],[4,3,1,2,6],[4,6,3,2,1],[4,6,3,1,2],[4,6,2,3,1],[4,6,2,1,3],[4,6,1,3,2],[4,6,1,2,3],[4,2,3,6,1],[4,2,3,1,6],[4,2,6,3,1],[4,2,6,1,3],[4,2,1,3,6],[4,2,1,6,3],[4,1,3,6,2],[4,1,3,2,6],[4,1,6,3,2],[4,1,6,2,3],[4,1,2,3,6],[4,1,2,6,3],[6,3,4,2,1],[6,3,4,1,2],[6,3,2,4,1],[6,3,2,1,4],[6,3,1,4,2],[6,3,1,2,4],[6,4,3,2,1],[6,4,3,1,2],[6,4,2,3,1],[6,4,2,1,3],[6,4,1,3,2],[6,4,1,2,3],[6,2,3,4,1],[6,2,3,1,4],[6,2,4,3,1],[6,2,4,1,3],[6,2,1,3,4],[6,2,1,4,3],[6,1,3,4,2],[6,1,3,2,4],[6,1,4,3,2],[6,1,4,2,3],[6,1,2,3,4],[6,1,2,4,3],[2,3,4,6,1],[2,3,4,1,6],[2,3,6,4,1],[2,3,6,1,4],[2,3,1,4,6],[2,3,1,6,4],[2,4,3,6,1],[2,4,3,1,6],[2,4,6,3,1],[2,4,6,1,3],[2,4,1,3,6],[2,4,1,6,3],[2,6,3,4,1],[2,6,3,1,4],[2,6,4,3,1],[2,6,4,1,3],[2,6,1,3,4],[2,6,1,4,3],[2,1,3,4,6],[2,1,3,6,4],[2,1,4,3,6],[2,1,4,6,3],[2,1,6,3,4],[2,1,6,4,3],[1,3,4,6,2],[1,3,4,2,6],[1,3,6,4,2],[1,3,6,2,4],[1,3,2,4,6],[1,3,2,6,4],[1,4,3,6,2],[1,4,3,2,6],[1,4,6,3,2],[1,4,6,2,3],[1,4,2,3,6],[1,4,2,6,3],[1,6,3,4,2],[1,6,3,2,4],[1,6,4,3,2],[1,6,4,2,3],[1,6,2,3,4],[1,6,2,4,3],[1,2,3,4,6],[1,2,3,6,4],[1,2,4,3,6],[1,2,4,6,3],[1,2,6,3,4],[1,2,6,4,3]]
Hope this helps.
Example with primitive array:
public static void permute(int[] intArray, int start) {
for(int i = start; i < intArray.length; i++){
int temp = intArray[start];
intArray[start] = intArray[i];
intArray[i] = temp;
permute(intArray, start + 1);
intArray[i] = intArray[start];
intArray[start] = temp;
}
if (start == intArray.length - 1) {
System.out.println(java.util.Arrays.toString(intArray));
}
}
public static void main(String[] args){
int intArr[] = {1, 2, 3};
permute(intArr, 0);
}
Visual representation of the 3-item recursive solution:
http://www.docdroid.net/ea0s/generatepermutations.pdf.html
Breakdown:
For a two-item array, there are two permutations:
The original array, and
The two elements swapped
For a three-item array, there are six permutations:
The permutations of the bottom two elements, then
Swap 1st and 2nd items, and the permutations of the bottom two element
Swap 1st and 3rd items, and the permutations of the bottom two elements.
Essentially, each of the items gets its chance at the first slot
A simple java implementation, refer to c++ std::next_permutation:
public static void main(String[] args){
int[] list = {1,2,3,4,5};
List<List<Integer>> output = new Main().permute(list);
for(List result: output){
System.out.println(result);
}
}
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
int size = factorial(nums.length);
// add the original one to the list
List<Integer> seq = new ArrayList<Integer>();
for(int a:nums){
seq.add(a);
}
list.add(seq);
// generate the next and next permutation and add them to list
for(int i = 0;i < size - 1;i++){
seq = new ArrayList<Integer>();
nextPermutation(nums);
for(int a:nums){
seq.add(a);
}
list.add(seq);
}
return list;
}
int factorial(int n){
return (n==1)?1:n*factorial(n-1);
}
void nextPermutation(int[] nums){
int i = nums.length -1; // start from the end
while(i > 0 && nums[i-1] >= nums[i]){
i--;
}
if(i==0){
reverse(nums,0,nums.length -1 );
}else{
// found the first one not in order
int j = i;
// found just bigger one
while(j < nums.length && nums[j] > nums[i-1]){
j++;
}
//swap(nums[i-1],nums[j-1]);
int tmp = nums[i-1];
nums[i-1] = nums[j-1];
nums[j-1] = tmp;
reverse(nums,i,nums.length-1);
}
}
// reverse the sequence
void reverse(int[] arr,int start, int end){
int tmp;
for(int i = 0; i <= (end - start)/2; i++ ){
tmp = arr[start + i];
arr[start + i] = arr[end - i];
arr[end - i ] = tmp;
}
}
Do like this...
import java.util.ArrayList;
import java.util.Arrays;
public class rohit {
public static void main(String[] args) {
ArrayList<Integer> a=new ArrayList<Integer>();
ArrayList<Integer> b=new ArrayList<Integer>();
b.add(1);
b.add(2);
b.add(3);
permu(a,b);
}
public static void permu(ArrayList<Integer> prefix,ArrayList<Integer> value) {
if(value.size()==0) {
System.out.println(prefix);
} else {
for(int i=0;i<value.size();i++) {
ArrayList<Integer> a=new ArrayList<Integer>();
a.addAll(prefix);
a.add(value.get(i));
ArrayList<Integer> b=new ArrayList<Integer>();
b.addAll(value.subList(0, i));
b.addAll(value.subList(i+1, value.size()));
permu(a,b);
}
}
}
}
Implementation via recursion (dynamic programming), in Java, with test case (TestNG).
Code
PrintPermutation.java
import java.util.Arrays;
/**
* Print permutation of n elements.
*
* #author eric
* #date Oct 13, 2018 12:28:10 PM
*/
public class PrintPermutation {
/**
* Print permutation of array elements.
*
* #param arr
* #return count of permutation,
*/
public static int permutation(int arr[]) {
return permutation(arr, 0);
}
/**
* Print permutation of part of array elements.
*
* #param arr
* #param n
* start index in array,
* #return count of permutation,
*/
private static int permutation(int arr[], int n) {
int counter = 0;
for (int i = n; i < arr.length; i++) {
swapArrEle(arr, i, n);
counter += permutation(arr, n + 1);
swapArrEle(arr, n, i);
}
if (n == arr.length - 1) {
counter++;
System.out.println(Arrays.toString(arr));
}
return counter;
}
/**
* swap 2 elements in array,
*
* #param arr
* #param i
* #param k
*/
private static void swapArrEle(int arr[], int i, int k) {
int tmp = arr[i];
arr[i] = arr[k];
arr[k] = tmp;
}
}
PrintPermutationTest.java (test case via TestNG)
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* PrintPermutation test.
*
* #author eric
* #date Oct 14, 2018 3:02:23 AM
*/
public class PrintPermutationTest {
#Test
public void test() {
int arr[] = new int[] { 0, 1, 2, 3 };
Assert.assertEquals(PrintPermutation.permutation(arr), 24);
int arrSingle[] = new int[] { 0 };
Assert.assertEquals(PrintPermutation.permutation(arrSingle), 1);
int arrEmpty[] = new int[] {};
Assert.assertEquals(PrintPermutation.permutation(arrEmpty), 0);
}
}
Here is one using arrays and Java 8+
import java.util.Arrays;
import java.util.stream.IntStream;
public class HelloWorld {
public static void main(String[] args) {
int[] arr = {1, 2, 3, 5};
permutation(arr, new int[]{});
}
static void permutation(int[] arr, int[] prefix) {
if (arr.length == 0) {
System.out.println(Arrays.toString(prefix));
}
for (int i = 0; i < arr.length; i++) {
int i2 = i;
int[] pre = IntStream.concat(Arrays.stream(prefix), IntStream.of(arr[i])).toArray();
int[] post = IntStream.range(0, arr.length).filter(i1 -> i1 != i2).map(v -> arr[v]).toArray();
permutation(post, pre);
}
}
}
Instead of permutations, we can preferably call them combinations.
Irrespective of the coding language, we can use a simple approach,
To append the array elements to the already existing list of combinations thus, using the dynamic programming approach.
This code focuses on those combinations without adjacency as well.
#include <iostream>
#include <vector>
using namespace std;
template <class myIterator, class T>
myIterator findDigit(myIterator first, myIterator last, T val)
{
while(first != last) {
if(*first == val) { break; }
first++;
}
return first;
}
void printCombinations(vector<vector<int>> combinations)
{
cout << "printing all " << combinations.size() << " combinations" << endl;
for(int i=0; i<combinations.size(); i++) {
cout << "[";
for(int j=0; j<combinations[i].size(); j++) {
cout << " " << combinations[i][j] << " ";
}
cout << "] , ";
}
return;
}
int main()
{
vector<int> a = {1,2,3,4,5};
vector<vector<int>> comb;
vector<int> t;
int len=a.size();
for(int i=0; i<len; i++) {
t.push_back(a.at(i));
comb.push_back(t);
t.clear();
}
for(int l=1; l<len; l++) {
for(int j=0; j<comb.size(); j++) {
if(comb[j].size()==l) {
int t = comb[j].back();
if(t != a.back()) {
vector<int>::iterator it = findDigit(a.begin(), a.end(), t);
for(std::vector<int>::iterator k=it+1; k!=a.end();k++) {
vector<int> t (comb[j].begin(), comb[j].end());
t.push_back(*k);
comb.push_back(t);
t.clear();
}
}
}
}
}
printCombinations(comb);
return 0;
}
Although the complexity is a bit high, it's definitely lower than the recursion approach, especially when the array size is very large.
Output for the above array (or vecter, if you will) is :
printing all 31 combinations
[ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ], [ 1 2 ], [ 1 3 ], [ 1 4 ], [ 1 5 ], [ 2 3 ], [ 2 4 ], [ 2 5 ], [ 3 4 ], [ 3 5 ], [ 4 5 ], [ 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 ], [ 1 2 3 4
], [ 1 2 3 5 ], [ 1 2 4 5 ], [ 1 3 4 5 ], [ 2 3 4 5 ], [ 1 2 3 4 5 ],
The code can be used for characters and strings as well, by just replacing the datatype wherever required.
eg.
vector<char> a = {'d','g','y','u','t'};
To give
printing all 31 combinations
[ d ] , [ g ] , [ y ] , [ u ] , [ t ] , [ d g ] , [ d y ] , [ d u ] , [ d t ] , [ g y ] , [ g u ] , [ g t ] , [ y u ] , [ y t ] ,
[ u t ] , [ d g y ] , [ d g u ] , [ d g t ] , [ d y u ] , [ d y t ] , [ d u t ] , [ g y u ] , [ g y t ] , [ g u t ] , [
y u t ] , [ d g y u ] , [ d g y t ] , [ d g u t ] , [ d y u t ] , [ g y u t ] , [ d g y u t ] ,
and
vector<string> a = {"asdf","myfl", "itshot", "holy"};
to give
printing all 15 combinations
[ asdf ] , [ myfl ] , [ itshot ] , [ holy ] , [ asdf myfl ] , [ asdf itshot ] , [ asdf holy ] , [ myfl itshot ] , [ myfl holy ] , [ itshot holy ] , [ asdf myfl itshot ] , [ asdf myfl holy ] , [ asdf itshot holy ] , [ myfl itshot holy ] , [ asdf myfl itshot holy ] ,

How to get unique integer pairs from an array of recurring pairs in Java?

The input values are 1,2,1,2,5,6,1,2,8,9,5,6,8,9.
The output should be in this form:
1,2 5,6 8,9
in a 2d string array. I tried this code but it's not working:
for(int u=0;u<=length_mfr/2;u=u+2)
{
for(int o=1;o<=length_mfr/2;o=o+2)
{
if(main_index[u][0]==main_index[u+2][o+2])
}
}
You're looking for unique pairs, not just unique numbers. Thus, the first step is to create a class to represent a pair.
public class Pair {
public final int first;
public final int second;
public Pair(int a, int b) {
first = a;
second = b;
}
public boolean equals(Object o) {
if (! (o instanceof Pair)) return false;
Pair p = (Pair)o;
return first == p.first && second == p.second;
}
public int hashCode() {
return first + second << 16;
}
public String toString() {
return "(" + first + "," + second + ")";
}
public String[] toStringArr() {
String[] s = new String[2];
s[0] = "" + first;
s[1] = "" + second;
return s;
}
}
From there you can turn your input in to pairs, do processing as necessary, and turn back into string array.
public static void main(String args[]){
int[] arr = { 1, 2, 1, 2, 5, 6, 1, 2, 8, 9, 5, 6, 8, 9 };
Set<Pair> set = new HashSet<>();
for(int i = 0; i < arr.length-1; i+=2) {
set.add(new Pair(arr[i], arr[i+1]));
}
String[][] arr2 = new String[set.size()][];
int i = 0;
for(Pair p : set) {
arr2[i] = p.toStringArr();
}
//Unique pairs now in string array arr2.
}
Given an int[] i with duplicates, you can create a TreeSet and add each element of the array i. TreeSet automatically removes duplicates and will contain only unique elements in ascending order.
public static void main(String args[])
{
int[] i = { 1, 2, 1, 2, 5, 6, 1, 2, 8, 9, 5, 6, 8, 9 };
Set<Integer> set = new TreeSet<>();
for (int e : i)
{
set.add(e);
}
// create an ArrayList to store all unique set values
// use Iterator to loop through ArrayList
ArrayList ar = new ArrayList<>(set);
Iterator it = ar.iterator();
// create index variable to loop through the str array
int index = 0;
// create String array str with the size of the set
String[] str = new String[set.size()];
while(it.hasNext() && index<set.size()){
str[index] = it.next().toString();
index++;
}
}
I hope this code will help you.
public static void main(String[] args) {
int[] num = { 1, 2, 1, 2, 5, 6, 1, 2, 8, 9, 5, 6, 8, 9 };
ArrayList<Integer> numDup = new ArrayList<Integer>();
numDup.add(num[0]);
for (int i = 0; i < num.length; i++) {
if (!numDup.contains(num[i])) {
numDup.add(num[i]);
}
}
for (Integer pVal : numDup) {
System.out.println(pVal);
}
}

How can I make this code to find a pair with a sum more efficient?

I'm doing this test on testdome.com for fun, and it's failing the efficiency test. What better way is there? I'm not counting any values twice. It seems the only way to do this is by brute force, which is an n^2 algorithm.
Here are the directions for the problem:
Write a function that, given a list and a target sum, returns
zero-based indices of any two distinct elements whose sum is equal to
the target sum. If there are no such elements, the function should
return null.
For example, findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12) should return
any of the following tuples of indices:
1, 4 (3 + 9 = 12),
2, 3 (5 + 7 = 12),
3, 2 (7 + 5 = 12) or
4, 1 (9 + 3 = 12).
And here's my code:
public class TwoSum {
public static int[] findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
for (int i = 0; i < list.length - 1; i++) { //lower indexed element
for (int j = i + 1; j < list.length; j++) { //higher indexed element
if (list[i] + list[j] == sum) {
return new int[]{i, j};
}
}
}
//none found
return null;
}
public static void main(String[] args) {
int[] indices = findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12);
System.out.println(indices[0] + " " + indices[1]);
}
}
EDIT: So here's my final working code. Thanks everyone!
import java.util.HashMap;
import java.util.Map;
public class TwoSum {
public static int[] findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
//map values to indexes
Map<Integer, Integer> indexMap = new HashMap<>();
for (int i = 0; i < list.length; i++) {
indexMap.put(list[i], i);
}
for (int i = 0; i < list.length; i++) {
int needed = sum - list[i];
if (indexMap.get(needed) != null) {
return new int[]{i, indexMap.get(needed)};
}
}
//none found
return null;
}
public static void main(String[] args) {
int[] indices = findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12);
System.out.println(indices[0] + " " + indices[1]);
}
}
As per Kon's suggestion, in one pass:
public static int[] findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
//map values to indexes
Map<Integer, Integer> indexMap = new HashMap<>();
for (int i = 0; i < list.length; i++) {
int needed = sum - list[i];
if (indexMap.get(needed) != null) {
return new int[]{i, indexMap.get(needed)};
}
indexMap.put(list[i], i);
}
//none found
return null;
}
Look at what you do in the inner loop, your checking if list[i] + list[j] == sum.
If you transform the equation slightly, it means given list[i] and sum (which are both constants within the inner loop), you are really asking "is there an index where the value (sum - list[i]) is stored", and thats what your inner loop solves.
Now applying the knowledge that you could solve the problem using essentially a indexOf(sum - list[i])-style method in linear time, there are data structures that can answer this kind of question in better time than O(N).
Here is linear solution (save sorting which is O(n*log(n)) ):
1) Sort your initial array a[]
2) let i be the first index of a[], and j - the last
i = 0;
j = a[].length - 1;
3) lets move from two ends:
do{
if(a[i]+a[j] < sum)
i++;
else if(a[i]+a[j] > sum)
j--;
else { // we have found required indexes!
put (i, j) to result set;
i++;
}
} while(i < j);
The final result - set of pairs (i,j) that give required sum. You can stop after first pair and return it.
P.S. if you have array like {3, 3, 3, 3, 9, 9, 9, 9} this solution will not give all the combinations:)
public static Map<Integer, Integer> findTwoSum(int[] list, int sum) {
if (list == null || list.length < 2) return null;
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
Map<Integer, Integer> arrayResult = new HashMap<Integer, Integer>();
for (int i = 0; i < list.length; i++) {
indexMap.put(list[i], i);
}
for (int i = 0; i < list.length; i++) {
int needed = sum - list[i];
if (indexMap.get(needed) != null) {
arrayResult.put(i, indexMap.get(needed));
}
}
return arrayResult.isEmpty()?null:arrayResult;
}
public static void main(String[] args) {
Map<Integer, Integer> indices = findTwoSum(new int[] { 1, 3, 5, 7, 9 }, 12);
System.out.println(indices);
}
Here's a solution written in C#. It should be easy enough to convert it over to Java lingo:
static public IEnumerable<Tuple<int, int>> FindAllTwoSumIndexes(IList<int> list, long desiredSum)
{
var count = list?.Count;
if (list == null || count <= 1)
return null;
var results = new List<Tuple<int, int>>(32);
var indexesMap = new ConcurrentDictionary<long, List<int>>(); //0 value-to-indexes
for (var i = 0; i < count; i++)
{
var thisValue = list[i];
var needed = desiredSum - thisValue;
if (indexesMap.TryGetValue(needed, out var indexes))
{
results.AddRange(indexes.Select(x => Tuple.Create(x, i)));
}
indexesMap.AddOrUpdate(
key: thisValue,
addValueFactory: x => new List<int> { i },
updateValueFactory: (x, y) =>
{
y.Add(i);
return y;
}
);
}
return results.Any() ? results.OrderBy(x => x.Item1).ThenBy(x => x.Item2).ToList() : null;
//0 bare in mind that the same value might be found over multiple indexes we need to take this into account
// also note that we use concurrentdictionary not for the sake of concurrency or anything but because we like
// the syntax of the addorupdate method which doesnt exist in the simple dictionary
}
Here is a Java program which find the pair of values in the array whose sum is equal to k using Hashtable or Set in the most efficient way.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class ArraySumUsingSet {
public static void main(String args[]) {
prettyPrint(getRandomArray(9), 11);
prettyPrint(getRandomArray(10), 12);
}
/**
* Given an array of integers finds two elements in the array whose sum is equal to n.
* #param numbers
* #param n
*/
public static void printPairsUsingSet(int[] numbers, int n){
if(numbers.length < 2){
return;
}
Set set = new HashSet(numbers.length);
for(int value : numbers){
int target = n - value;
// if target number is not in set then add
if(!set.contains(target)){
set.add(value);
}else {
System.out.printf("(%d, %d) %n", value, target);
}
}
}
/*
* Utility method to find two elements in an array that sum to k.
*/
public static void prettyPrint(int[] random, int k){
System.out.println("Random Integer array : " + Arrays.toString(random));
System.out.println("Sum : " + k);
System.out.println("pair of numbers from an array whose sum equals " + k);
printPairsUsingSet(random, k);
}
/**
* Utility method to return random array of Integers in a range of 0 to 15
*/
public static int[] getRandomArray(int length){
int[] randoms = new int[length];
for(int i=0; i<length; i++){
randoms[i] = (int) (Math.random()*15);
}
return randoms;
}
}
Output
Random Integer array : [0, 14, 0, 4, 7, 8, 3, 5, 7]
Sum : 11
pair of numbers from an array whose sum equals 11
(7, 4)
(3, 8)
(7, 4)
Random Integer array : [10, 9, 5, 9, 0, 10, 2, 10, 1, 9]
Sum : 12
pair of numbers from an array whose sum equals 12
(2, 10)

Array even & odd sorting

I have an array where I have some numbers. Now I want to sort even numbers in a separate array and odd numbers in a separate. Is there any API to do that? I tried like this
int[] array_sort={5,12,3,21,8,7,19,102,201};
int [] even_sort;
int i;
for(i=0;i<8;i++)
{
if(array_sort[i]%2==0)
{
even_sort=Arrays.sort(array_sort[i]);//error in sort
System.out.println(even_sort);
}
}
Plain and simple.
int[] array_sort = {5, 12, 3, 21, 8, 7, 19, 102, 201 };
List<Integer> odd = new ArrayList<Integer>();
List<Integer> even = new ArrayList<Integer>();
for (int i : array_sort) {
if ((i & 1) == 1) {
odd.add(i);
} else {
even.add(i);
}
}
Collections.sort(odd);
Collections.sort(even);
System.out.println("Odd:" + odd);
System.out.println("Even:" + even);
Your question as stated doesn't make sense, and neither does the code. So I'm guessing that you want to separate the elements of an array into two arrays, one containing odds and the other evens. If so, do it like this:
int[] input = {5, 12, 3, 21, 8, 7, 19, 102, 201};
List<Integer> evens = new ArrayList<Integer>();
List<Integer> odds = new ArrayList<Integer>();
for (int i : input) {
if (i % 2 == 0) {
evens.add(i);
} else {
odds.add(i);
}
}
You can then convert a list of Integer to a sorted array if int as follows:
List<Integer> list ...
int[] array = new int[list.size()];
for (int i = 0; i < array.length; i++) {
array[i] = list.get(i);
}
Arrays.sort(array);
or if a sorted List<Integer> is what you need, just do this:
Collections.sort(list);
It's simple to do this using Guava.
Use Ints.asList to create a List<Integer> live view of an int[]
Define a Function<Integer,Boolean> isOdd
Use Ordering that compares onResultOf(isOdd), naturally (i.e. false first, then true)
If necessary, compound that with an Ordering.natural()
Here's the snippet:
int[] nums = {5,12,3,21,8,7,19,102,201};
Function<Integer,Boolean> isOdd = new Function<Integer,Boolean>() {
#Override
public Boolean apply(Integer i) {
return (i & 1) == 1;
}
};
Collections.sort(
Ints.asList(nums),
Ordering.natural().onResultOf(isOdd)
.compound(Ordering.natural())
);
System.out.println(Arrays.toString(nums));
// [8, 12, 102, 3, 5, 7, 19, 21, 201]
Note that all the even numbers show up first, then all the odd numbers. Within each group, the numbers are sorted naturally.
External links
polygenelubricants.com - Writing more elegant comparison logic with Guava's Ordering
There are some things to know first :
You must initialize an array before using it. For example int[] even_sort = new int[3];
In java arrays have a static size. That means that you won't be able to add as many elements as you want. You have to choose a size before. You should take a look at Java Collections, it's a good way to get rid of this "rule" the java way.
The Arrays.sort() method apply on arrays only. Here array_sort[i] is an int
Arrays.sort() sorts an array but doesn't return anything.
If you really want to use arrays (but you shouldn't) you can do something like this to resize one :
int[] even_sort = new int[3]{1, 2, 3};
int[] temp = new int[4];
System.arraycopy(even_sort, 0, temp, 0, even_sort.length);
even_sort = temp;
even_sort[3] = 4;
Another way would be creating an utility method which uses reflection to create the new array :
import java.lang.reflect.Array;
public Object resizeArray(Object originalArray, int newSize){
int originalSize = Array.getLength(originalArray);
Class arrayType = originalArray.getClass().getComponentType();
Object newArray = Array.newInstance(arrayType, newSize);
System.arraycopy(originalArray, 0, newArray, 0, Math.min(originalSize, newSize));
return newArray;
}
So if you still want to use array for some reasons (but you still shouldn't) here is a code to filter, resize and sort your array.
int[] arrayToFilterAndSort = {5, 12, 3, 21, 8, 7, 19, 102, 201};
int[] sortedEvens = new int[0];
for(int current : arrayToFilterAndSort){
if((current & 1) == 1){
sortedEvens = resizeArray(sortedEvens, sortedEvens.length + 1);
sortedEvens[sortedEvens.length - 1] = current;
}
}
Arrays.sort(sortedEvens);
Resources :
oracle.com - Arrays tutorial
oracle.com - Collections tutorial
javadoc - Arrays.sort()
package com.java.util.collection;
import java.util.Arrays;
/**
* Given n random numbers. Move all even numbers on left hand side and odd numbers on right hand side and
* then sort the even numbers in increasing order and odd numbers in decreasing order For example,
* i/p : 3 6 9 2 4 10 34 21 5
* o/p: 2 4 6 10 34 3 5 9 21
* #author vsinha
*
*/
public class EvenOddSorting {
public static void eventOddSort(int[] arr) {
int i =0;
int j =arr.length-1;
while(i<j) {
if(isEven(arr[i]) && isOdd(arr[j])) {
i++;
j--;
} else if(!isEven(arr[i]) && !isOdd(arr[j])) {
swap(i,j,arr);
} else if(isEven(arr[i])){
i++;
} else{
j--;
}
}
display(arr);
// even number sorting
Arrays.sort(arr,0,i);
Arrays.sort(arr,i,arr.length);
// odd number sorting
display(arr);
}
public static void display(int[] arr) {
System.out.println("\n");
for(int val:arr){
System.out.print(val +" ");
}
}
private static void swap(int pos1, int pos2, int[] arr) {
int temp = arr[pos1];
arr[pos1]= arr[pos2];
arr[pos2]= temp;
}
public static boolean isOdd(int i) {
return (i & 1) != 0;
}
public static boolean isEven(int i) {
return (i & 1) == 0;
}
public static void main(String[] args) {
int arr[]={3, 6, 9 ,2, 4, 10, 34, 21, 5};
eventOddSort(arr);
}
}
int arr[20] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "The Even no are : \n";
for (int i = 1; i <= 10; i++) // for start for only i....(even nos)
{
if (i % 2 == 0)
{
cout << i;
cout << " ";
}
}
cout << "\nThe Odd no are : \n";
for (int j = 1; j <= 10; j++) // for start for only j....(odd nos)
{
if (j % 2 != 0)
{
cout << j;
cout << " ";
}`enter code here`
}
package srikanth dukuntla;
public class ArrangingArray {
public static void main(String[] args) {
int j=0;
int []array={1,2,3,5,4,55,32,0};
System.out.println(array.length);
int n=array.length/2;
for (int i=0; i<array.length; i++){
if(array[i]%2!=0){
j=1;
int temp=array[array.length-j];
if(temp % 2!=0){
while((array[array.length-(j+1)]%2!=0) && (array.length-(j+1)>n)){
j++;
}
int temp2=array[array.length-(j+1)];
array[array.length-(j+1)] =array[i];
array[i]=temp2;
}else // inner if
{
array[array.length-j] =array[i];
array[i]=temp;
}
}else //main if
{
//nothing needed
}
}
for(int k=0;k<array.length;k++) {
System.out.print(" "+ array[k]);
}
}
}
List < Integer > odd = new ArrayList < Integer > ();
List < Integer > even = new ArrayList < Integer > ();
int a [] = {0,2,3,98,1,6546,45323,1134564};
int i;
for (i = 0; i < a.length; i++) {
if (a[i] % 2 == 0) {
even.add(a[i]);
} else {
odd.add(a[i]);
}
}
System.out.print("Even: " + even + "\n");
System.out.print("Uneven: " + odd + "\n");
}
}

Categories

Resources