Related
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]
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).
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);
What is the best way to concatenate two arrays with alternating values?
Let's say array1 is:
[1, 3, 5, 7]
array2 is:
[2, 4, 6, 8]
I want to combine these two arrays, so that the result is:
[1, 2, 3, 4, 5, 6, 7, 8]
In Java:
int[] a1 = { 1, 3, 5, 7 };
int[] a2 = { 2, 4, 6, 8 };
int[] concat = new int[a1.length * 2];
for (int i = 0; i < concat.length; i++) {
// concatenation
}
System.out.println(concat.toString());
// should be [1, 2, 3, 4, 5, 6, 7, 8]
Update: No sorting is required, as the arrays are already sorted, using Arrays.sort(array)
A basic way
int[] concat = new int[a1.length * 2];
int index = 0;
for (int i = 0; i < a1.length; i++) {
concat[index++] = a1[i];
concat[index++] = a2[i];
}
assuming that both array will be of same size.
Put the elements of both array in a list and then sort it.You can use lambdas also
Integer[] a1 = { 1, 3, 5, 7 };
Integer[] a2 = { 2, 4, 6, 8 };
List<Integer> list = new ArrayList<>();
list.addAll(Arrays.asList(a1));
list.addAll(Arrays.asList(a2));
System.out.println("Before Sorting "+list);
Collections.sort(list,(a, b) -> Integer.compare(a,b));
System.out.println("After Sorting "+list);
Output
Before Sorting [1, 3, 5, 7, 2, 4, 6, 8]
After Sorting [1, 2, 3, 4, 5, 6, 7, 8]
If you want to zip together any length arrays (where then lengths differ, the remaining is appended to the result):
public static int[] zip(int[] a, int[] b){
int[] result = new int[a.length + b.length];
int index = 0;
final int minLen = Math.min(a.length, b.length);
for (int i = 0; i < minLen; i++) {
result[index++] = a[i];
result[index++] = b[i];
}
if(a.length > minLen)
System.arraycopy(a, minLen, result, index, a.length - minLen);
else if(b.length > minLen)
System.arraycopy(b, minLen, result, index, b.length - minLen);
return result;
}
Try it like this:
int[] concat = new int[a1.length + a2.length];
int k = 0, m = 0;
for (int i = 0; i < concat.length; i++) {
if( k < al.length && a1[k] <= a2[m])
concat[i] = a1[k++];
else
concat[i] = a2[m++];
}
NB: The result will be sorted as in your desired output.
you could also use two variables in your loop like this
int[] a1 = { 1, 3, 5, 7 };
int[] a2 = { 2, 4, 6, 8 };
int[] concat = new int[a1.length + a2.length];
for (int i = 0, j = 0; i+j < concat.length;) {
if(i<a1.length) {
concat[i+j] = a1[i++];
}
if(j<a2.length) {
concat[i+j] = a2[j++];
}
}
System.out.println(Arrays.toString(concat));
Try This if it solves ur problem
int[] a1 = { 1, 3, 5, 7 };
int[] a2 = { 2, 4, 6, 8 };
int[] concat = new int[a1.length + a2.length];
System.arraycopy(a1, 0, concat, 0, a1.length);
System.arraycopy(a2, 0, concat, a1.length, a2.length);
Arrays.sort(concat);
System.out.println(Arrays.toString(concat));
Output:
[1, 2, 3, 4, 5, 6, 7, 8]
There are utility methods for example addALL() method from ArrayUtil class. But what they do is simple concatenate. For your problem you need to write your own logic. For example the following code ensures correct alternate concatenation even if arrays are of unequal length.
int[] a1 = { 1, 3, 5, 7 };
int[] a2 = { 2, 4, 6, 8, 9, 10, 122 };
int totalLen = a1.length + a2.length;
int[] concat = new int[totalLen];// I made a change here incase the
// arrays are not of equal length
int i = 0; // this will be the concat array index counter
int j1 = 0; // this will be the a1 array index counter
int j2 = 0; // this will be the a2 array index counter
while (i < totalLen) {
if ((j1 < a1.length)) {
concat[i] = a1[j1];
i++;
j1++;
}
if ((j2 < a2.length)) {
concat[i] = a2[j2];
i++;
j2++;
}
}
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.