How to count unique values in java - java

I want to count the number of unique values in an array but I'm having trouble counting in the correct way.
int uniqueNumbers = 1;
Arrays.sort(n);
if (n.length == 0) {
uniqueNumbers = 0;
}
for ( int i = 1; i < n.length; i++) {
if (n[i] != n[i - 1]) {
uniqueNumbers++;
}
}
The problem is if an integer appears several times it still counts it as one unique number, when I want it not to be counted as a unique number.

you can utilize a set to add all the numbers, as won't allow duplicates.
int uniqueNumbers = 1;
Set<Integer> set = new HashSet<>();
Arrays.sort(n);
if (n.length == 0) {
uniqueNumbers = 0;
}
for ( int i = 0; i < n.length; i++) {
set.add(n[i];
}
System.out.println(set.size());

A nested loop to track a unique number and discard it can help resolve this task:
public static int countUnique(int ... n) {
Arrays.sort(n);
System.out.println(Arrays.toString(n));
int uniqueNumbers = 0;
for (int i = 0; i < n.length; i++) {
boolean unique = true;
for (int j = i + 1; j < n.length && n[i] == n[j]; j++, i++) {
unique = false;
}
if (unique) {
uniqueNumbers++;
}
}
return uniqueNumbers;
}
Tests:
System.out.println(countUnique(2, 1, 2, 3, 4, 6, 4));
System.out.println(countUnique(2, 1, 2, 3, 4, 1, 4));
System.out.println(countUnique(2, 1, 2, 4, 4, 1, 4));
Output:
[1, 2, 2, 3, 4, 4, 6]
3
[1, 1, 2, 2, 3, 4, 4]
1
[1, 1, 2, 2, 4, 4, 4]
0
However, because of sorting the input array, the complexity of this algorithm is O(N log N).
If it is allowed to use Set to track duplicates using the fact that Set::add returns false when an element already exists in the set, this may be implemented as follows (also, the input array does not need to be sorted, so this algorithm has O(N) complexity):
public static int countUniqueSets(int ... n) {
System.out.println(Arrays.toString(n));
Set<Integer> ones = new HashSet<>();
Set<Integer> dups = new HashSet<>();
for (int x : n) {
if (!ones.add(x)) {
dups.add(x);
}
}
System.out.println("distinct: " + ones);
System.out.println("duplicates: " + dups);
return ones.size() - dups.size();
}
Output for the same tests:
[2, 1, 2, 3, 4, 6, 4]
distinct: [1, 2, 3, 4, 6]
duplicates: [2, 4]
3
[2, 1, 2, 3, 4, 1, 4]
distinct: [1, 2, 3, 4]
duplicates: [1, 2, 4]
1
[2, 1, 2, 4, 4, 1, 4]
distinct: [1, 2, 4]
duplicates: [1, 2, 4]
0
Another approach using Stream API is to build a frequency map using Collectors.groupingBy + Collectors.counting or Collectors.summingInt and then count the entries in the map with frequency = 1:
public static int countUniqueStream(int ... n) {
System.out.println(Arrays.toString(n));
return (int) Arrays.stream(n)
.boxed()
.collect(Collectors.groupingBy(
x -> x,
Collectors.counting()
)) // Map<Integer, Long>
.entrySet()
.stream()
.filter(e -> 1 == e.getValue())
.count();
}
public static int countUniqueStreamInt(int ... n) {
System.out.println(Arrays.toString(n));
return Arrays.stream(n)
.boxed()
.collect(Collectors.groupingBy(
x -> x,
Collectors.summingInt(x -> 1)
)) // Map<Integer, Integer>
.entrySet().stream()
.filter(e -> 1 == e.getValue())
.collect(Collectors.summingInt(e -> 1));
}

There are so many ways to do so e.g. using Stream API.
Demo:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
int [] arr= {1,2,3,4,2,3,4,1,4,3};
long uniqueCount = Arrays.stream(arr)
.distinct()
.count();
System.out.println(uniqueCount);
}
}

You can put the array content to set and then get the set size.
Set<Integer> targetSet = new HashSet<Integer>(Arrays.asList(n));
targetSet.size()
n is your array name as appearing in the question

You don't need a whole inner loop, you just need to check the two adjacent numbers while respecting the array limits.
private int countUnique (int... n)
{
int uniqueNumbers = 0;
if (n.length < 2)
{
uniqueNumbers = n.length;
}
else
{
Arrays.sort (n);
logger.info ("Data %s", Arrays.toString (n));
// Check first element
if (n[0] != n[1])
{
uniqueNumbers++;
}
// Check last element
if (n[n.length - 2] != n[n.length - 1])
{
uniqueNumbers++;
}
// Check middle elements
for (int i = 1; i < n.length - 1; i++)
{
if ((n[i - 1] != n[i]) && (n[i + 1] != n[i]))
{
uniqueNumbers++;
}
}
}
return uniqueNumbers;
}

Related

How to sort array based on multiples of 3 using Java

I have an array like this one-
{1, 2, 3, 4, 5, 6}
I want to sort it in the order of multiples of 3 with remainders 0, 1 and 2. (the first group is multiples of 3, the second one is multiples of 3 with remainder 1 and the last one is multiples of 3 with remainder 2) and I want to preserve the order in which elements appear in the array.
The result should be -
{3, 6, 1, 4, 2, 5}
I have this code-
int current = 0;
int b = 0;
for (int i = 0; i < 3; i++) { //3 groups
for (int j = current; j < numbers.length; j++) {
if (numbers[j] % 3 == i) { //reminder should be 0,1 or 2
b = numbers[j];
numbers[j] = numbers[current];
numbers[current] = b;
current++;
}
}
}
But this code does not preserve the order in which elements appear in the array. The result I got is-
{3, 6, 1, 4, 5, 2}
But I want the result to be like {3, 6, 1, 4, 2, 5}. How can I achieve this?
Using stream and comparator
int[] array = {1, 2, 3, 4, 5, 6};
List<Integer> lst = Arrays.stream(array)
.boxed()
.sorted(Comparator.comparingInt(o -> o % 3))
.collect(Collectors.toList());
System.out.println(lst);
In your solution you are swapping the elements in place, which shuffles them from the initial order. That's why you don't have the same ordering at the end. I'm not sure if there is another way apart from having a second array to keep the sorted elements, while at the same time iterating over the original one like so:
public static void main(String[] args) {
int[] numbers = new int[]{1, 2, 3, 4, 5, 6};
int[] result = new int[numbers.length];
int b = 0;
int current = 0;
for (int i = 0; i < 3; i++) { //3 groups
for (int j = 0; j < numbers.length; j++) {
if (numbers[j] % 3 == i) { //reminder should be 0,1 or 2
result[current] = numbers[j];
current++;
}
}
}
System.out.println(Arrays.toString(result));
}
Output: [3, 6, 1, 4, 2, 5]
You can use an IntStream and a Comparator to sort the stream:
int[] arr = {1, 2, 3, 4, 5, 6};
int[] arrSorted = IntStream.of(arr).boxed()
.sorted(Comparator.comparingInt(i -> i % 3))
.mapToInt(Integer::intValue)
.toArray();
System.out.println(Arrays.toString(arrSorted));
Output:
[3, 6, 1, 4, 2, 5]
Note: From IntStream.of() javadoc:
Returns a sequential ordered stream whose elements are the specified
values.
I would create a new array of the same size and then place the elements in the correct order. For example like this:
int[] array = {1, 2, 3, 4, 5, 6};
int[] sorted = new int[array.length];
int counter = 0;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < array.length; j++) {
if (array[j] % 3 == i) {
sorted[counter] = array[j];
counter++;
}
}
}
System.out.println(Arrays.toString(sorted));
Output:
[3, 6, 1, 4, 2, 5]
Alternatively, you can use Java 8 features to reduce the amount of code like this:
int[] array = {1, 2, 3, 4, 5, 6};
int[] sorted = Arrays.stream(array).boxed().sorted(Comparator.comparingInt(a -> (a % 3))).mapToInt(i -> i).toArray();
Output:
[3, 6, 1, 4, 2, 5]

Reverse subset of ArrayList using multidimensional ArrayList in Java

I am trying to reverse a sublist in a List using the indices provided in a multidimensional List.
I don't have much experience using multidimensional lists/arrays. I don't understand why this doesn't work.
/*
Given a List<Integer> list and List<List<Integer>> operations
reverse the sublist and print out the list after all the operations have been done.
Ex: [5, 3, 2, 1, 3]
[[0,1], [1, 3]]
*/
import java.util.*;
public class ReverseParameters {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> operations = new ArrayList<>(2);
for(int i= 0; i < 3; i++){
operations.add(new ArrayList<>());
}
operations.get(0).add(1);
operations.get(1).add(3);
subList(list, operations);
}
public static void subList (List<Integer> list, List<List<Integer>> operations) {
System.out.println(list);
int vertCount = operations.size();
for (int i = 0; i < vertCount; i++) {
int edgeCount = operations.get(i).size();
for (int j = 0; j < edgeCount; j++) {
int startInd = i;
int endInd = operations.get(i).get(j);
int shift = endInd - startInd;
int right = Math.min(i + shift - 1, list.size() - 1);
int temp = 0;
while (startInd < right) {
temp = list.get(startInd);
list.set(startInd, list.get(right));
list.set(right, temp);
startInd+=1;
right-=1;
}
System.out.println();
System.out.printf(" %d %d%n", startInd, endInd);
System.out.println();
}
}
System.out.println(list);
}
}
The output of this code using [[0,1], [1, 3]] as the indecies is:
[5, 2, 3, 1, 3]
but it should be:
[3, 1, 2, 5, 3]
Can someone please help point me in the right direction?
This can be done as simple as this.
public class Main
{
public static void main(String[] args)
{
//Given a List<Integer> list and List<List<Integer>> operations
//reverse the sublist and print out the list after all the operations have been done.
//Ex: [5, 3, 2, 1, 3]
// [[0,1], [1, 3]]
//Target: [3, 1, 2, 5, 3]
//Steps:
// 0 1 2 3 4 (Indices)
//###############
//[5, 3, 2, 1, 3]
//[3, 5, 2, 1, 3] // Swap index of 0 and 1.
//[3, 1, 2, 5, 3] // Swap index of 1 and 3.
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> listOfList = new ArrayList<List<Integer>>(2);
listOfList.add(Arrays.asList(0, 1));
listOfList.add(Arrays.asList(1, 3));
for(int i=0; i < listOfList.size(); ++i) {
final int indexA = listOfList.get(i).get(0); //[0 , [1
final int indexB = listOfList.get(i).get(1); // 1], 3]
//Swap the indices.
final int tmpValue = list.get(indexA);
list.set(indexA, list.get(indexB));
list.set(indexB, tmpValue);
}
System.out.println(list);
//[3, 1, 2, 5, 3]
}
}
You are overcomplicating your code with unnecessary variables that makes it difficult to find the problem. Please se a more simple code with explanation:
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> operations = new ArrayList<>(2);
// Initialize your operations
operations.add(Arrays.asList(0,1));
operations.add(Arrays.asList(1,3));
subList(list, operations);
}
public static void subList (List<Integer> list, List<List<Integer>> operations) {
// You just iterate over the operations
for (List<Integer> operation : operations) {
// For each operation, store left and right indexes.
int left = operation.get(0);
int right = operation.get(1);
// Iterate until both indexes find each other
while (left < right) {
// Swap left and right elements in input list
int aux = list.get(left);
list.set(left, list.get(right));
list.set(right, aux);
// Now you move your indexes
++left;
--right;
}
}
System.out.println(list);
}
Please note that, depending on what the question asks, you may also need to verify if the operations indexes are within the list boundaries so you won't end up getting an ArrayIndexOutOfBoundsException. So be always careful with edge cases.
You can get subset by List.subList() , and reverse by Collections.reverse().
static void reverseSubsets(List<Integer> list, List<List<Integer>> subsets) {
for (List<Integer> subset : subsets)
Collections.reverse(list.subList(subset.get(0), subset.get(1) + 1));
}
public static void main(String[] args) {
List<Integer> list = Arrays.asList(5, 3, 2, 1, 3);
List<List<Integer>> subsets = List.of(List.of(0, 1), List.of(1, 3));
reverseSubsets(list, subsets);
System.out.println(list);
}
output:
[3, 1, 2, 5, 3]
Note:
toIndex in List.subList(int fromIndex, int toIndex) is exclusive high endpoint of the subList. So you must add 1 to subset.get(1).

How do you split an Array List into sublists everytime there is a duplicate value in the Array List

I have the following array list which contains the following
point ids (1,2,3,4,1,8,5,6,8,9,7,9). I am using Java 7
I was wondering how it could be split into sublists i.e the sublists below
(1,2,3,4,1)
(8,5,6,8)
(9,7,9)
I have had problems trying to use a loop within a loop (i.e check each point
from the outer loop with each of the other points in the inner loop) to get
index positions (starPosIndex and endPosIndex) where there are duplicate point ids and ArrayList.sublist(startPosIndex,endPosIndex) to get the correct sublist
int startPos = 0;
int endPos = 0;
for (int j = 0; j < polygonList3.size(); j++){
Point pointToCheck = polygonList3.get(j);
for (int k = 1; k < polygonList3.size(); k++){
Point pointToCheck2 = polygonList3.get(k);
if (pointToCheck.getID() == pointToCheck2.getID()){
startPos = startPos + endPos;
endPos = endPos + k;
//startPos = startPos + endPos;
//for (int startPos = j; startPos < polygonList3.size(); startPos = (startPos) + endPos) {
//endPos = Math.min(startPos + endPos, polygonList3.size());
finalPolygonLists.add(new ArrayList<Point>(polygonList3.subList(startPos, endPos)));//originalPtsSublist2);
//}
}
}
I would solve it in the following manner:
Allocate a HashSet to contain unique values encountered
Allocate a new list for the first sublist
Iterate over the whole list, adding each value to the set. When we encounter a value that is already in the set, we are done with the first sublist, so clear the set, and allocate a new sublist
After iteration, you will have your list of sublists, obtained in O(n) runtime
You can walk along the list, and create slices of the list (using List#subList) as you go. This can be done efficiently, by always checking whether the first element of the current segment of the list appears somewhere else in the list. If it does, you can store this "slice", and continue with the "tail" of the list. If it doesn't, you are finished (and the tail of the list may or may not be part of the result - that's up to you)
Implemented here as an example:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListSlicing
{
public static void main(String[] args)
{
runTest(1,2,3,4,1,8,5,6,8,9,7,9);
runTest(1,2,3,4);
runTest(1,1,1,1);
runTest(1,2,1,2,1,2,1,2,1,2,1,2);
runTest();
}
private static void runTest(Integer ... numbers)
{
List<Integer> list = Arrays.asList(numbers);
System.out.println("Input: "+list);
System.out.println("Output: "+slices(list));
}
private static <T> List<List<T>> slices(List<T> input)
{
List<List<T>> slices = new ArrayList<List<T>>();
List<T> current = input;
while (current.size() > 0)
{
T first = current.get(0);
int appearance = current.subList(1, current.size()).indexOf(first);
if (appearance == -1)
{
slices.add(current);
return slices;
}
List<T> slice = current.subList(0, appearance+2);
slices.add(slice);
current = current.subList(appearance+2, current.size());
}
return slices;
}
}
The output is
Input: [1, 2, 3, 4, 1, 8, 5, 6, 8, 9, 7, 9]
Output: [[1, 2, 3, 4, 1], [8, 5, 6, 8], [9, 7, 9]]
Input: [1, 2, 3, 4]
Output: [[1, 2, 3, 4]]
Input: [1, 1, 1, 1]
Output: [[1, 1], [1, 1]]
Input: [1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
Output: [[1, 2, 1], [2, 1, 2], [1, 2, 1], [2, 1, 2]]
Input: []
Output: []
The following code tracks the last position for each number and as soon as it founds a duplicate, it will create the sublist and clears all previously tracked entries.
List<Integer> list = Arrays.asList( 1,2,3,4,1,8,5,6,8,9,7,9);
List<List<Integer>> sublists = new ArrayList<>();
Map<Integer,Integer> lastPos = new HashMap<>();
for(int i = 0; i < list.size(); i++) {
Integer current = list.get(i);
if(lastPos.containsKey(current)){
sublists.add(list.subList(lastPos.get(current), i+1));
lastPos.clear();
} else {
lastPos.put(current, i);
}
}
System.out.println(sublists);

Integer partition iterative code optimization

I have been working on code to iteratively partition integers and use previous results to fully partition the numbers, with the idea that using previous partitions can increase speed. So far, I have gotten performance 22x slower than recursively partitioning the integers, and haven't been able to test larger numbers due to quickly running out of memory. If anyone could help optimize the code, I would be grateful for the help.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Collectors;
public class Summands {
private static HashMap<Integer, HashSet<List<Integer>>> results;
private static HashMap<Integer, HashSet<String>> recursiveResults;
private static void sort(int[] a) {
//Radix sort for int array
int i, m = a[0], exp = 1, n = a.length;
int[] b = new int[n];
for (i = 1; i < n; i++) {
if (a[i] > m) {
m = a[i];
}
}
while (m / exp > 0) {
int[] bucket = new int[n];
for (i = 0; i < n; i++)
bucket[(a[i] / exp) % n]++;
for (i = 1; i < n; i++)
bucket[i] += bucket[i - 1];
for (i = n - 1; i >= 0; i--)
b[--bucket[(a[i] / exp) % n]] = a[i];
for (i = 0; i < n; i++)
a[i] = b[i];
exp *= n;
}
}
private static void generateResults(int n) {
//iterative partitioning
results.put(n, new HashSet<>());
results.get(n).add(new ArrayList<>());
for (List<Integer> list : results.get(n)) {
list.add(n);
}
for (int i = 1; i <= Math.floorDiv(n, 2); i++) {
//get all 2 summands partitions
int a = n - i;
results.get(n).add(Arrays.asList(i, a));
}
if (n > 1) {
//Get the rest of the partitions
HashSet<List<Integer>> set = new HashSet<>(results.get(n));
for (List<Integer> equ : set) {
if (equ.size() > 1) {
if (equ.get(1) > 1) {
HashSet<List<Integer>> temp = results.get(equ.get(1));
for (List<Integer> k : temp) {
List<Integer> tempEquList = new ArrayList<>(k);
tempEquList.add(equ.get(0));
int[] tempEqu = tempEquList.stream()
.mapToInt(Integer::intValue).toArray();
sort(tempEqu);
results.get(n).add(Arrays.stream(tempEqu)
.boxed().collect(Collectors.toList()));
}
}
}
}
}
}
private static void recursivePartition(int n) {
//recursively partition
recursiveResults.put(n, new HashSet<>());
partition(n, n, "", n);
}
private static void partition(int n, int max, String prefix, int key) {
//recursive method for partitioning
if (n == 0) {
recursiveResults.get(key).add(prefix);
return;
}
for (int i = Math.min(max, n); i >= 1; i--) {
partition(n - i, i, prefix + " " + i, key);
}
}
public static void main(String[] args) {
//get number of partitions to get
int target = Integer.valueOf(args[0]);
//time the iterative version
long time1 = System.currentTimeMillis();
results = new HashMap<>(target);
//loop until done
for (int i = 1; i <= target; i++) {
System.out.println(i);
generateResults(i);
}
//time both methods
long time2 = System.currentTimeMillis();
recursiveResults = new HashMap<>(target);
for (int i = 1; i <= target; i++) {
//loop until done
System.out.println(i);
recursivePartition(i);
}
long time3 = System.currentTimeMillis();
System.out.println("Iterative time: " + String.valueOf(time2 - time1));
System.out.println("Recursive time: " + String.valueOf(time3 - time2));
/*for (Integer key : results.keySet()) {
//For ensuring proper amount of partitions
//for lower numbers. Primarily for testing
System.out.println(key + ": " + results.get(key).size());
}*/
}
}
You can generate a set of combinations of the summands of the specified number, i.e. the integer partition, using mapToObj and reduce methods. First prepare the sets of arrays of summands, and then multiply the pairs of these sets sequentially and get the Cartesian product.
Try it online!
int n = 7;
Set<int[]> partition = IntStream.range(0, n)
// prepare sets of arrays of summands
.mapToObj(i -> IntStream.rangeClosed(1, n - i)
.mapToObj(j -> new int[]{j})
// Stream<TreeSet<int[]>>
.collect(Collectors.toCollection(
// comparing the contents of two arrays
() -> new TreeSet<>(Arrays::compare))))
// intermediate output, sets of arrays of summands
.peek(set -> System.out.println(
set.stream().map(Arrays::toString).collect(Collectors.joining())))
// sequential summation of pairs of sets up to the given number
.reduce((set1, set2) -> set1.stream()
// combinations of inner arrays
.flatMap(arr1 -> {
// sum of the elements of the first array
int sum = Arrays.stream(arr1).sum();
// if the specified number is reached
if (sum == n) return Arrays.stream(new int[][]{arr1});
// otherwise continue appending summands
return set2.stream() // drop the combinations that are greater
.filter(arr2 -> Arrays.stream(arr2).sum() + sum <= n)
.map(arr2 -> Stream.of(arr1, arr2)
.flatMapToInt(Arrays::stream)
.sorted().toArray()); // the sorted array
}) // set of arrays of combinations
.collect(Collectors.toCollection( // two arrays that differ
// only in order are considered the same partition
() -> new TreeSet<>(Arrays::compare))))
// otherwise an empty set of arrays
.orElse(new TreeSet<>(Arrays::compare));
// final output, the integer partition of the specified number
partition.stream().map(Arrays::toString).forEach(System.out::println);
Intermediate output, sets of arrays of summands:
[1][2][3][4][5][6][7]
[1][2][3][4][5][6]
[1][2][3][4][5]
[1][2][3][4]
[1][2][3]
[1][2]
[1]
Final output, the integer partition of the specified number:
[1, 1, 1, 1, 1, 1, 1]
[1, 1, 1, 1, 1, 2]
[1, 1, 1, 1, 3]
[1, 1, 1, 2, 2]
[1, 1, 1, 4]
[1, 1, 2, 3]
[1, 1, 5]
[1, 2, 2, 2]
[1, 2, 4]
[1, 3, 3]
[1, 6]
[2, 2, 3]
[2, 5]
[3, 4]
[7]
See also: Building permutation that sums to a number efficiently

Go through all permutations of an array recursively

I am trying to write a recursive function to produce all permutations of an array.
static int permus[] = new int[] { 1, 2, 3, 4, 5 };
static void testPermu(int start)
{
// Print it
System.out.println(Arrays.toString(permus));
int k;
for (int i = start + 1; i < permus.length; i++) {
// swap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
testPermu(i);
// unswap
k = permus[start];
permus[start] = permus[i];
permus[i] = k;
}
}
It's invoked as testPermu(0) and should produce all permutations, however that does not work. How can I fix it?
It needs to be recursive, each time the function is invoked, it should get a fresh permutation.
output now is
[1, 2, 3, 4, 5]
[2, 1, 3, 4, 5]
[2, 3, 1, 4, 5]
[2, 3, 4, 1, 5]
[2, 3, 4, 5, 1]
[2, 3, 5, 4, 1]
[2, 4, 3, 1, 5]
[2, 4, 3, 5, 1]
[2, 5, 3, 4, 1]
[3, 2, 1, 4, 5]
[3, 2, 4, 1, 5]
[3, 2, 4, 5, 1]
[3, 2, 5, 4, 1]
[4, 2, 3, 1, 5]
[4, 2, 3, 5, 1]
[5, 2, 3, 4, 1]
You can see that many of the permutations are missing.
I'm writing it in Java but I'll understand example in C, javascript or anything else as long as it's not using some library tricks not available in Java.
Three corrections are needed in order to work:
print only if (start == permus.length-1), otherwise you'll see duplicates
start the for loop from i = start, not i = start + 1
recursively call testPermu(start + 1); instead of testPermu(i);
Here is a full example:
package eric.math;
import java.util.Arrays;
public class Permute {
// swap 2 elements of an array,
void swap(int[] arr, int x, int y) {
int temp = arr[x];
arr[x] = arr[y];
arr[y] = temp;
}
/**
* print permutations of array
* #param arr
* original int array,
*/
void permute(int[] arr) {
permute(arr, 0, arr.length - 1);
}
/**
* print permutations of array
*
* #param arr
* original int array,
* #param i
* start index
* #param n
* end index
*/
void permute(int[] arr, int i, int n) {
int j;
if (i == n)
System.out.println(Arrays.toString(arr));
else {
for (j = i; j <= n; j++) {
swap(arr, i, j);
permute(arr, i + 1, n);
swap(arr, i, j); // backtrack
}
}
}
public static void main(String[] args) {
int arr[] = { 1, 2, 3 };
new Permute().permute(arr);
}
}
#Enric solution is nice, but using solution below we can avoid 80 swaps and perform only 24 swaps.
static void permutation(int[] a, int i, int j) {
for (; j < a.length && i < a.length; j++) {
int[] temp = null;
if (i != j) {
temp = swap(a, i, j);
System.out.println(Arrays.toString(temp));
}else{
temp = a;
}
permutation(temp, i + 1, i + 1);
}
}
public static void main(String[] args) {
int[] a = { 0, 1, 2, 3 };
permutation(a, 0, 0);
}
Another approach:
static ArrayList<ArrayList<Integer>> getPermutation(ArrayList<Integer> ints) {
if (ints.size() == 1) {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
list.add(ints);
return list;
} else {
ArrayList<ArrayList<Integer>> list = new ArrayList<>();
for (Integer i: ints) {
ArrayList<Integer> subList = new ArrayList<>(ints);
subList.remove(i);
ArrayList<ArrayList<Integer>> subListNew = getPermutation(subList);
for (ArrayList<Integer> _list: subListNew) {
ArrayList<Integer> local = new ArrayList<>();
local.add(i);
local.addAll(_list);
list.add(local);
}
}
return list;
}
}
This method first selects an element, removes it and obtains a sub-list, then produces a permutation of the sub-list until the list size becomes 1.
I like #tony200910041 approach but maybe someone would like a cleaner and more generic version of it:
public static <T> List<List<T>> getPermutations(List<T> list) {
if (list.size() == 1)
return Collections.singletonList(list);
List<List<T>> perms = new ArrayList<>();
for (T element: list) {
List<T> subList = new ArrayList<>(list);
subList.remove(element);
List<List<T>> subPerms = getPermutations(subList);
for (List<T> subPerm: subPerms) {
List<T> perm = new ArrayList<>();
perm.add(element);
perm.addAll(subPerm);
perms.add(perm);
}
}
return perms;
}
Sort the list before passing it to the getPermutations() function if you want your permutations in ascending order.
Try with
testPermu(start + 1);
You can do it simply without recursion
public static Integer[] permutate(int i)
{
int length = permus.length;
Integer[] result = new Integer[length];
List<Integer> chosen = new ArrayList<Integer>(Arrays.asList(permus));
int divider = 1;
for (int j=2; j<length; j++)
{
divider *= j;
}
for (int j=length; j>1; j--)
{
int index = i/divider;
result[length - j] = chosen.remove(index);
i = i - divider * (i/divider);
divider = divider / (j-1);
}
result[length -1] = chosen.remove(0);
return result;
}
How about the following algorithm (given in pseudocode)
iterate over elements:
pick one of the element at random
call function again on the remaining elements
if elements.size == 1
return or print
This should produce a valid permutation at each run. If you want all possible permutations, just accumulate as you iterate, then you should have all permutations.

Categories