find longest linked lists in an array of linked lists - java

I have an array of linked lists (an adjacency list) most of the lengths of the linked lists are 4 but there are some that will randomly have more than that. My goal is to go through the array and find the ones that are more than length 4 (thats the easy part) then add the index's to an array so something like
for (int i = 0; i < 1000; i++){
if(sWorld[i].length > 4)
//add i to an array
// then sort the array
couldnt really figure out how to do this. i tried to add to a inked list then linked list toArray() but then it was messing up. i just dont really know how to add the 'i' point in my sWorld array to say the first position in the new array im going to use for the ones that are grater than size 4.
Any help would be much appreciated!
EDITED TO CLARIFY A BIT
i need the indexes of the the locations that are size > 4, but then i want to know which of those indexes that i get have the greatest size. Maybe i wasnt 100% clear in my op, but basically im trying to find which of the 1000 indexes in the array have the most connections (the longest linked list) make sense?
I want to know the top 10 connected indexes of the array (aka which 10 have the greatest size of linked list)

You can use an ArrayList to store the indexes:
List<Integer> indexes = new ArrayList<Integer>();
for (int i = 0; i < 1000; i++){
if (sWorld[i].length > 4) {
//add i to a list (not an array yet)
indexes.add(i);
}
...
}
// then sort the list
// not necessary, as indexes are inserted in the right order, but if you must...
// Collections.sort(indexes);
// and, if you need an array instead of a list
Integer[] indexesArray = indexes.toArray(new Integer[indexes.size()]);
A List, or an ArrayList, work as variable-length arrays. Though not as efficiently as an actual array.
As seen above, there is no need to sort the array later, but, if you must, you can use Collections.sort().
Also, if you must have an int[] instead of an Integer[], please check: How to convert List<Integer> to int[] in Java?
Update:
As you want to know the size and index of the bigger arrays, it's a whole new problem. Below is a working code that deals with it.
Basically, everytime you find an array with size larger than 4, you add a pair (index, size) to the list. This list is then ordered by size, in descending order.
At the end of the main() method, an array is created (int[] topTenIndexes) which contains the indexes of the 10 biggest arrays (the indexes are presented in descending order of it's array's length). The result is -1 when there weren't enough big (length > 4) arrays.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class Example {
public static void main(String[] args) {
List<ArrayIndexAndSize> indexes = new ArrayList<ArrayIndexAndSize>();
int[][] sWorld = {{1},{2,5,5,5,5},{3,6,6,6,6,6}};
for (int i = 0; i < sWorld.length; i++){
if (sWorld[i].length > 4) {
// add a pair (index, size) to the list
indexes.add(new ArrayIndexAndSize(i, sWorld[i].length));
}
//...
}
// then sort the list by array SIZE, in descending order
Collections.sort(indexes);
// Print it!
System.out.println(indexes);
/* output:
"[[Array index: 2; Array size: 6], [Array index: 1; Array size: 5]]"
*/
// Generating an array with the top ten indexes
int[] topTenIndexes = new int[10];
Arrays.fill(topTenIndexes, -1);
for (int i = 0; i < indexes.size() && i < 10; i++) {
topTenIndexes[i] = indexes.get(i).index;
}
// Print it
System.out.println(Arrays.toString(topTenIndexes));
/* output: [2, 1, -1, -1, -1, -1, -1, -1, -1, -1] */
}
public static class ArrayIndexAndSize implements Comparable<ArrayIndexAndSize> {
public int index;
public int size;
public ArrayIndexAndSize(int index, int size) {
this.index = index;
this.size = size;
}
/* Order by size, DESC */
/* This is called by Collections.sort and defines the order of two elements */
public int compareTo(ArrayIndexAndSize another) {
int thisVal = this.size;
int anotherVal = another.size;
return -(thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
}
#Override
public String toString() {
return "[Array index: "+index+"; Array size: "+size+"]";
}
}
}

If you have an array LinkedList<?>[] sWorld (fill the type you're using in for ?), then do this:
ArrayList<Integer> listOfLists = new ArrayList<>();
for (int i=0; i<sWorld.size(); i++) {
if (sWorld[i].size > 4) {
listOfLists.add(i);
}
}
Comparator<Integer> sizeComparator = new Comparator<Integer>() {
public int compare(Integer a, Integer b) {
return Integer.compare(sWorld[a].size(), sWorld[b].size());
}
}
Collections.sort(listOfLists, sizeComparator);

Related

Minimum number of Groups needed to convert the given Array to another Array

I have a given array with unique values say [1,4,3,2] and another desired array [1,2,4,3]
I want to cut this input array into a minimum number of pieces so I can convert that to the desired array by just re-arranging the cut pieces.
So for the input array [1,4,3,2] I can cut into pieces (1), (4,3), (2) and re-arrange like (1),(2),(4,3) to get the desired array [1,2,4,3]
Constraints:
Array values are unique.
The size of both arrays is the same and can be up to 1000.
Values in arrays are integers
So the answer is 3 pieces for this example.
Here is what I have tried:
public int process(int[] inp, int[] desired) {
int ans = 0;
for (int i = 0; i < inp.length; i++) {
if (inp[i] != desired[i]) ans++;
}
return ans;
}
My approach is not a correct one, as I am finding elements at each index to count the mismatches. What is the correct approach for solving this problem?
Since all elements in the given arrays are unique, we can store index the positions of elements in one of these arrays by generating a map of type Map<Integer,Integer> associating an array element (Key) with its index (Value).
Then iterate over the second array, searching for identical chunks.
For that, we need to maintain a variable prevIndex that would store the index occupied by the previous element in the first array. While iterating, we would need to check each next index in the first array (corresponding to the next element in the first array). If the next index differs from the previous only by one - the next element is proved to be a part of a chunk with identical order, and we're just incrementing prevIndex. Otherwise, increment the count of chunks.
public static int process(int[] arr1, int[] arr2) {
Map<Integer, Integer> indexByValue = mapIndices(arr2);
int count = 1;
int prevIndex = indexByValue.get(arr1[0]);
for (int i = 1; i < arr1.length; i++) {
int nextIndex = indexByValue.get(arr1[i]);
if (nextIndex == prevIndex + 1) {
prevIndex++;
} else {
prevIndex = nextIndex;
count++;
}
}
return count;
}
public static Map<Integer, Integer> mapIndices(int[] arr) {
return IntStream.range(0, arr.length)
.boxed()
.collect(Collectors.toMap(
i -> arr[i],
Function.identity()
));
}
main()
public static void main(String[] args) {
System.out.println(process(new int[]{1, 4, 3, 2}, new int[]{1, 2, 4, 3}));
}
Output:
3

How to insert an integer into a sorted List in Java?

I would like to write a function insertAndSort() that will take as parameter an Integer "num" and a List of integers "list". Let's assume the List lust is already sorted.
The algorithm is supposed to work this way :
Add "num" to L and keep the List sorted after "num" has been added.
Return the sorted List.
WARNING : We do not know whether the list is sorted ASC or DESC. And that is precisely my problem !
Example :
if "num" = 4 and L = {1, 3, 5, 7}, then the final sorted List is {1, 3, 4, 5, 7}
if "num" = 4 and L = {7, 5, 3, 1}, then the final sorted List is {7, 5, 4, 3, 1}
I can not use sorting API such as Collections.sort or Collections.reverseOrder etc...
So far, I've produced this code :
public static void main(String[] args) {
int num = 4;
List<Integer> myList = Arrays.asList(1, 3, 5, 7);
List<Integer> newList = new ArrayList<Integer>();
newList = insertAndSort(myList, num);
System.out.println(newList);
}
public static List<Integer> insertAndSort(List<Integer> list, int num) {
List<Integer> listSecond = new ArrayList<Integer>(list.size()+1);
for(int i = 0; i <= list.size() ; i++) {
if(num < list.get(i)) {
if(!listSecond.contains(num)){
listSecond.add(num);
} else {
listSecond.add(list.get(i-1));
listSecond.add(list.get(i));
break;
}
} else {
listSecond.add(list.get(i));
}
}
return listSecond;
}
The problem is that this seems to be working with a single type of List: the ascending one.
When I take a sorted descending List, it does not work anymore.
Do you have any idea to make this work with both type of List ?
Thanks and Regards.
First, you need to detect the sort order in the existing list.
If the list is empty, you don’t need to care, just add your element, you cannot break any existing sort order.
If the list contains one element, I cannot tell you what to do. Options include tossing a coin and throwing an exception, but there are more.
If the list contains two or more elements, iterate through them except for the last element, each time comparing the current element with the element in the next higher index. As soon as you encounter a pair of elements that are not equal, you know the sort order. If you only encounter equal elements, all the elements in the list are equal, and again I cannot tell you what to do.
Once you’ve detected a sort order, I suggest a big if-else statement to handle the two cases separately.
You already have the code for the ascending case. Except it doesn’t always work. If I try to insert 4 into { 1, 3, 5 }, I get an ArrayIndexOutOfBoundsException. If I try with { 1, 3, 5, 7, 9 }, the 9 is lost. You should probably find a fix for that.
You should be able to handle the descending case similarly to the ascending case. Only use num > list.get(i) instead of num < list.get(i).
First, you need to check whether the list is sorted in ASC or DESC. That's easy: compare the 1st two elements look for two consecutive non-identical elements and see whether the first one is greater or the second one (thanks tom for correcting the mistake).
Now, for a list sorted in ascending order, convert list to an ArrayList. Then, add num to the ArrayList and convert it to a TreeSet, since TreeSets sort their elements in ascending order. Finally, reassign the ArrayList to hold the contents of the TreeSet and return it.
For a list sorted in descending order, first, convert the TreeSet to an ArrayList, then iterate over this ArrayList in reverse order and add the elements to a new ArrayList. Return the second ArrayList.
public List<Integer> insertAndSort(List<Integer> list, int num){
ArrayList<Integer> a = new ArrayList<Integer>(list);
a.add(new Integer(num));
TreeSet t = new TreeSet(a);
a = new ArrayList<Integer>(t);
int l = list.size();
for(int i=1; i<l; i++){
if(list.get(i) != list.get(i-1))
break;
}
if(list.get(i) > list.get(i-1)) //ASC
return a;
else{ //DESC
ArrayList<Integer> a2 = new ArrayList<Integer>();
for(int i = a.size() - 1; i >= 0; i--)
a2.add(a.get(i));
return a2;
}
}
I would proceed with something like the code below. A few remarks :
it is possible to decide sort order if and only if there is at least 1 element AND first and last elements have different values.
the line int oo = list.get(p2) - list.get(p1); compute the
difference between the last and first element (negative = DESC,
positive = ASC)
the variable ox is positive if and only if the
added element is after the element pointed by the variable p3
whatever the order.
the position is found by a binary search algorithm by choosing p3 between p1 and p2 and deciding if the element is before or after p3.
This is not fully tested bu works with the examples you gave :
// static List<Integer> list = new ArrayList<>(Arrays.asList(7, 5, 3, 1));
static List<Integer> list = new ArrayList<>(Arrays.asList(1, 3, 5, 7));
static void add(int x)
{
// fixed code below (see Ole V.V. comment)
}
static public void main(String [ ] args)
{
add(4);
for(int x: list)
System.out.println(x);
}
EDIT: to be complete (see Ole V.V. comments)
When the new element is to be inserted before the first or after the last, two simple O(1) tests may be performed ; the general case has O(log N) complexity, this is more efficient than traversing the entire list which is O(N).
Be carefull too when comparing elements to deduce sort order, there may be several equal values ; the best is to compare the first and the last elements, this is O(1) - again better than O(N).
Algorithmic complexity is an important matter (to me) and was the primary aim of my post. The code of the add function becomes :
static void add(int x)
{
int p1 = 0;
int p2 = list.size() - 1;
if(list.size() == 0 || list.get(p1) == list.get(p2))
throw new IllegalStateException("Unable to decide sort order");
int oo = list.get(p2) - list.get(p1);
if(oo * (x - list.get(p1)) <= 0) // new element is before first
list.add(0, x);
else if(oo * (x - list.get(p2)) >= 0) // new element is after last
list.add(x);
else
{
while (p1 + 1 < p2)
{
int p3 = (p1 + p2) / 2;
int ox = (x - list.get(p3)) * oo;
if(ox >= 0) // new element is after p3
p1 = p3;
if(ox <= 0) // new element is before p3
p2 = p3;
}
list.add(p2, x);
}
}
Note : there may be still some undealed side effects. If the asker is interested, I am ready to give further help - just ask.
Your code and what you say is two different things.
Based on code you made, I see that List can't contain more than one instance of same value.
If thats the case, main method should look like this:
public static void main(String[] args){
int num = 4;
List<Integer> myList = Arrays.asList(1, 3, 4, 5, 7);
List<Integer> newList;
if (!myList.contains(num)) {
newList = insertAndSort(myList, num);
} else {
newList = copyList(myList);
}
System.out.println(newList);
}
if thats not the case:
public static void main(String[] args){
int num = 4;
List<Integer> myList = Arrays.asList(1, 3, 4, 5, 7);
List<Integer> newList;
newList = insertAndSort(myList, num);
System.out.println(newList);
}
Methods that main method use:
Assuming we can only know how list is sorted by values in list, we have to decide default sort method when there is only 1 value or all values are same. I picked ASC as default. If elements can be of same value and we are certain list is sorted its best to compare lowest value in list with the highest one. With this approach we have to compare 2 elements only once.
So method to see if list is sorted DESC would look like this:
private static boolean isDesc(List<Integer> list) {
return list.get(0) > list.get(list.size() - 1);
}
If method returns true its sorted DESC. With returning false its ASC. If we want to change default value, when values don't tell us how its sorted and we want it to be DESC we would replace '>' sign with '>='
private static boolean isDesc(List<Integer> list) {
return list.get(0) >= list.get(list.size() - 1);
}
Code for as you called it insertAndSort:
public static List<Integer> insertAndSort(List<Integer> list, int num) {
List<Integer> listSecond = new ArrayList<Integer>(list.size() + 1);
boolean isDescSortOrder = isDesc(list);
if (isDescSortOrder) {
int i = 0;
while ((i < list.size()) && (list.get(i) > num)) {
listSecond.add(list.get(i));
i++;
}
listSecond.add(num);
while (i < list.size()) {
listSecond.add(list.get(i));
i++;
}
} else { // is asc sort order
int i = 0;
while ((i < list.size()) && (list.get(i) < num)) {
listSecond.add(list.get(i));
i++;
}
listSecond.add(num);
while (i < list.size()) {
listSecond.add(list.get(i));
i++;
}
}
return listSecond;
}
Depending on how its sorted code got devided into 2 blocks. As we don't know on each iteration will be right place to insert our num value its better to use while loop. Using for loop and checking everytime if num value already exists in list is counterproductive. On top of that I dunno if your application should allow same values in the list. If I assume it should, you can't add num value if it already existed in the list with for loop and checking with contains every iteration.
And just to copy the table when list already has the element and we don't want to add elements that are already incuded:
public static List<Integer> copyList(List<Integer> list) {
List<Integer> listSecond = new ArrayList<Integer>(list.size());
for (int i = 0; i < list.size(); i++) {
listSecond.add(list.get(i));
}
return listSecond;
}
Also based on good programming practices I'd recommend to name methods based on what they do.
Calling method insertAndSort is asking for trouble. If I seen it, I'd say it alters list we are giving in parameter. Then it sorts it.
So putting unsorted list in it would give us unwanted outcome.
And I'd still ask myself why does it return a List when we are inserting an item to already existing list? I'd rather name it:
public static List<Integer> copySortedWithNewValue(List<Integer> sortedList, int newValue)
Try to use PriorityQueue. This collection contains a sorted sequence of elements which could be duplicated.

Randomly prints elements in an array

Is there a way where you can use Math.random to prints the element in a given array?
int[] list = new int[] {1,2,3};
So the output will be like
2,1,3
or
3,1,2
or
2,3,1
Perhaps you can approach it by shuffling your array then print it. If the original should not be modified, you can make a copy and then shuffle the copy.
There are well-known algorithms for shuffling array (or a deck of cards). One can be found here. An implementation in java looks like this:
static void shuffleArray(int []array) {
int length = array.length;
for (int i = length -1; i > 0; i--) {
// generate a random 0 <= j < i
int j = (int)(Math.random() * i);
// swap elements at i and j
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
The approach proposed in most answers is extremely inefficient, as it works in O(N2) time. Think about it: at first you'll generate unused indexes with one attempt, but closer to the end, when almost all array is processed, it will require nearly N steps to generate next unused index.
The optimal O(N) approach is to create shuffled array of indexes (0..N) where each index appears only once and then process your original array in the order of shuffled indexes. Each step requires O(N) time, so the whole algorithm is O(N).
int[] input = new int[]{5, 4, 3, 6, 2, 1};
int []indices = new int[input.length];
//Fisher-Yates shuffle
Random rnd = new Random();
for (int i = 0; i < indices.length; i++) {
int j = rnd.nextInt(i + 1);
indices[i] = indices[j];
indices[j] = i;
}
for (int i : indices) {
System.out.println(input[i]);
}
I didn't use Collections.shuffle, as it would require usage of Collection and thus wrapped Integer elements, which is very inefficient comparing to the plain int array.
Also, if you are ok with modifying your original array, you can just shuffle it in place (using the same Fisher-Yates shuffle) and then consume it while traversing.
UPD: Replaced shuffling array of indices with shuffled initialization.
Since you have java 8, you can take advantage of the beautiful Stream API.
In short, you can do:
new Random().ints(1, 500).limit(500).forEach(p -> System.out.println(list[p]));
Where 1 is the lowest int generated (inclusive) and 500 is the highest (exclusive). limit means that your stream will have a length of 500, maybe in that argument you want to put list.length.
For your case:
int[] list = new int[] {1,2,3,4,5,6};
new Random().ints(0, list.length).limit(10).forEach(p -> System.out.println(list[p]));
Prints: 5 2 5 4 6 3 3 5 6 4 (Obviously will not print the same numbers for you)
Create a random integer that may be as high as the length of the array - 1. If the random integer is equal to a previous used random integer -- known by storing used integers in an array -- create a new random integer. Otherwise, print the string correlated with that index specified by the random integer. If the length of the array storing the used random integers is equal to the length of the array of strings, stop the process.
This should print all your strings only once each and randomly.
Here is the solution
public static void main(String[] args) {
int[] list = new int[] { 1, 2, 3 };
int[] aux = new int[list.length];
int countTimes = 0;
while (countTimes < list.length) {
int position = new Random().nextInt(list.length);
if (aux[position] != list[position]) {
System.out.println(list[position]);
aux[position] = list[position];
countTimes++;
}
}
}
As I said in the comments. This answer will work.. All you need to do is track the indices that it accessed so you don't repeat them or remove that element from the array.
void printRandom(int[] array) {
if (array.length == 0)
return;
Random rand = new Random();
int rnd = rand.nextInt(array.length);
int element = array[rnd];
array = ArrayUtils.removeElement(array, element);
System.out.print(element);
printRandom(array);
}
Just repeat this process until all elements are removed. Obviously add checks to prevent errors and keep in mind I haven't used JAVA in a long time so post back if you have issues!
Lastly keep in mind this deletes the array so you may want to wrap this code in a function and then copy the array as a local variable so you can reuse the original as needed
In this case we can print random value from array using like below :
Steps:
Create list object of Integer to hold printed indices
Get random number and check whether this index is already printed or not
if not printed then add it in list and print value from array using this index
if list size and array length is equal then terminate the loop
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class RandomIndices {
public static void main(String[] args) {
int[] list = new int[]{1, 2, 3};
Random random = new Random();
List<Integer> randomIndices = new ArrayList<>(); //to hold indices which are already printed
boolean isRemain = true;
while (isRemain) {
int randomIndex = random.nextInt(list.length);
if (!randomIndices.contains(randomIndex)) { //check random index value of array is printed or not
randomIndices.add(randomIndex);
System.out.println(list[randomIndex]);
}
if (randomIndices.size() == list.length) {
isRemain = false;
}
}}
}
Implement a simple "do while" statement to prevent duplicate numbers from showing up out of your array (I used a StringArray - but an IntegerArray would work the same way - as a side note, I can place the complete code up here but didn't want to do so if it didn't apply. I use a drop-down to select how many random words to generate - then display that set of true RANDOM words (non-repeated):
final Random rand1 = new Random();
final Random rand2 = new Random();
final int rndInt1 = rand1.nextInt(getResources().getStringArray(R.array.words).length);
int rndInt2 = rand2.nextInt(getResources().getStringArray(R.array.words).length);
if (rndInt1 == rndInt2){
do {
rndInt2 = rand2.nextInt(getResources().getStringArray(R.array.words).length);
}while (rndInt1 == rndInt2);//if indexes are equal - re-run the array search
}
outString = getResources().getStringArray(R.array.words)[rndInt1];
outString += ", " + getResources().getStringArray(R.array.words)[rndInt2];//concatenate the list
textWord = (TextView) findViewById(R.id.textWords);//An empty text field in my layout
textWord.setText(outString);//Set that empty text field to this string of random array elements

php's array_multisort function equivalent in java

I was looking for an equivalent of *php's array_multisort* in java.
//array 1
ar1 = array(10, 100, 100, 0);
//array 2
ar2 = array(1, 3, 2, 4);
//calling the function
//this will sort the array at first based one the first array and then based on the
//second array so these two array are related
array_multisort(ar1, ar2);
//resultant 1st array
array(4) {
[0]=> int(0)
[1]=> int(10)
[2]=> int(100)
[3]=> int(100)
}
//resultant 2nd array
//this array has been sorted based on the first array at first
array(4) {
[0]=> int(4) // this is associative element of 0 in the first array
[1]=> int(1) //this is associative element of 10 in the first array
[2]=> int(2) //this is associative element of 1st 100 from the last in the first array
//as there are two 100's , and last one's associative value in the second
//array is smaller it will come first
[3]=> int(3)
}
how can i achieve this result using something built-in , i know how to implement it using custom code.
N.B. *Please visit this link before answering the question as that explains how the function should work*
This is a bit more complicated and can't be done without the Java standard API. So I have recycled a quicksort implementation and made it work for multiple arrays. Basically it swaps the elements when they are swapped by the partitioning of quicksort.
Here you go:
/**
* Multi-sorts the given arrays with the quicksort algorithm. It assumes that
* all arrays have the same sizes and it sorts on the first dimension of these
* arrays. If the given arrays are null or empty, it will do nothing, if just
* a single array was passed it will sort it via {#link Arrays} sort;
*/
public static void multiQuickSort(int[]... arrays) {
multiQuickSort(0, arrays);
}
/**
* Multi-sorts the given arrays with the quicksort algorithm. It assumes that
* all arrays have the same sizes and it sorts on the given dimension index
* (starts with 0) of these arrays. If the given arrays are null or empty, it
* will do nothing, if just a single array was passed it will sort it via
* {#link Arrays} sort;
*/
public static void multiQuickSort(int sortDimension, int[]... arrays) {
// check if the lengths are equal, break if everything is empty
if (arrays == null || arrays.length == 0) {
return;
}
// if the array only has a single dimension, sort it and return
if (arrays.length == 1) {
Arrays.sort(arrays[0]);
return;
}
// also return if the sort dimension is not in our array range
if (sortDimension < 0 || sortDimension >= arrays.length) {
return;
}
// check sizes
int firstArrayLength = arrays[0].length;
for (int i = 1; i < arrays.length; i++) {
if (arrays[i] == null || firstArrayLength != arrays[i].length)
return;
}
multiQuickSort(arrays, 0, firstArrayLength, sortDimension);
}
/**
* Internal multi quicksort, doing the real algorithm.
*/
private static void multiQuickSort(int[][] a, int offset, int length,
int indexToSort) {
if (offset < length) {
int pivot = multiPartition(a, offset, length, indexToSort);
multiQuickSort(a, offset, pivot, indexToSort);
multiQuickSort(a, pivot + 1, length, indexToSort);
}
}
/**
* Partitions the given array in-place and uses the end element as pivot,
* everything less than the pivot will be placed left and everything greater
* will be placed right of the pivot. It returns the index of the pivot
* element after partitioning. This is a multi way partitioning algorithm, you
* have to provide a partition array index to know which is the array that
* needs to be partitioned. The swap operations are applied on the other
* elements as well.
*/
private static int multiPartition(int[][] array, int start, int end,
int partitionArrayIndex) {
final int ending = end - 1;
final int x = array[partitionArrayIndex][ending];
int i = start - 1;
for (int j = start; j < ending; j++) {
if (array[partitionArrayIndex][j] <= x) {
i++;
for (int arrayIndex = 0; arrayIndex < array.length; arrayIndex++) {
swap(array[arrayIndex], i, j);
}
}
}
i++;
for (int arrayIndex = 0; arrayIndex < array.length; arrayIndex++) {
swap(array[arrayIndex], i, ending);
}
return i;
}
/**
* Swaps the given indices x with y in the array.
*/
public static void swap(int[] array, int x, int y) {
int tmpIndex = array[x];
array[x] = array[y];
array[y] = tmpIndex;
}
Done a little testcase to test your input from the question:
#Test
public void testMultiQuickSort() {
int[] first = new int[] { 10, 100, 100, 0 };
int[] second = new int[] { 1, 3, 2, 4 };
int[] resFirst = new int[] { 0, 10, 100, 100 };
int[] resSecond = new int[] { 4, 1, 2, 3 };
ArrayUtils.multiQuickSort(first, second);
for (int i = 0; i < first.length; i++) {
assertEquals(resFirst[i], first[i]);
assertEquals(resSecond[i], second[i]);
}
}
Seems to work ;)
BTW if you need it for an arbitrary object type, just leave a comment.
A multi-dimensional array is just an array of arrays, so iterate over the individual arrays and sort them:
int[][] marr = // your multi-dimensional array here
for (int[] arr : marr) {
Arrays.sort(arr);
}
And if, for whatever possible reason, you only want to sort the first array in the second dimension, this will do:
Arrays.sort(marr[0]);
Argh, now I understand what you want. If your elements (at least those of the first array) are unique, you can do it via a SortedMap:
if(arr1.length!=arr2.length)throw new IllegalArgumentException();
SortedMap<Integer,Integer> map = new TreeMap<Integer, Integer>();
for (int i = 0; i < arr1.length; i++) {
map.put(arr1[i],arr2[i]);
}
int ct = 0;
for (Entry<Integer, Integer> entry : map.entrySet()) {
arr1[ct]=entry.getKey();arr2[ct]=entry.getValue();
ct++;
}
It's look like that there is not any built-in library function / class for this purpose in Java .
If you are also facing this problem like me , so far Thomas's answer about the custom code can help you.
implements Comparator or using algorithm bubble sort
Arrays.sort(stringArray); it will sort only one array
Maybe the following code will help you.
You should use Arrays.sort()
Example:
import java.util.Arrays;
String [] stringArray = {"ab", "aB", "c", "0", "2", "1Ad", "a10"};
//order Ascending
Arrays.sort(stringArray);
//Descending
Arrays.sort(stringArray, Collections.reverseOrder());

How to sort one array list and set the another list with same order in java

I have three array lists with String .I want to sort one arraylist and with same order want to set the element of other two list in java. i can sort one list but how to set element of other two list with sorted list order.
Thanks and regards
Rahul
By far the best way to do this would be to rethink the design and put all three pieces of related data into instances of class designed for this purpose, then just sort the one ArrayList.
Any other method would involve either setting up some Maps to hold the relationships between the Strings, and then manually moving the lists around after sorting the first one (a difficult mess) or writing your own sorting algorithm which moved the second two lists in tandem with the first (probably easier, but an even worse mess.)
private void sortingMechanism() {
for(int i=0;i<list1.size();i++){
for(int j=i+1;j<list1.size();j++){
if(list1.get(i)>list1.get(j)){
Collections.swap(list1, i, j);
Collections.swap(list2, i, j);
Collections.swap(list3, i, j);
}
}
}
}
If you wrote the sorting code yourself, just expand the part of the code that modifies you first array to modify the other two arrays in the same fashion.
Though the optimal way is to refactor your code to make one list with objects in them that contain the information of all three arrays.
Just as Ernest says :)
When you sort the first array list instead of only interchanging the elements in the first array list do it also for the other too, using the same index.
arraylist1[x]=arraylist1[y];
arraylist2[x]=arraylist2[y];
arraylist3[x]=arraylist3[y];
Of course there are additional steps when interchanging (like assigning to the auxiliary variable) but that's not what I wanted to show here.
This is a common need.
One option (and you get to use Java's sort, which is probably better than the one you'll write):
/**
* Sorts by the first list
*/
static void sort(List... lists) {
assert lists.length > 0;
Object[][] objects = new Object[lists[0].size()][lists.length];
for (int i = 0; i < lists.length; i++) {
int j = 0;
for (Object object : lists[i]) {
objects[j++][i] = object;
}
}
Arrays.sort(objects, new Comparator<Object[]>() {
public int compare(Object[] o1, Object[] o2) {
return ((Comparable)o1[0]).compareTo(o2[0]);
}
});
for (int i = 0; i < lists.length; i++) {
lists[i].clear();
for (Object[] tuple : objects) {
lists[i].add(tuple[i]);
}
}
}
Use it like
List<String> a = new ArrayList<String>(Arrays.asList(new String[]{"dog", "cat", "cat"}));
List<Integer> b = new LinkedList<Integer>(Arrays.asList(new Integer[]{1, 2, 3}));
List<Object> c = new Vector<Object>(Arrays.asList(new Object[]{"object", 0.5, new Object()}));
sort(a, b, c);
System.out.println(a);
System.out.println(b);
System.out.println(c);
One disadvantage to using this is that it depends on .clear() which is not implemented for some lists, but you could adapt it in that case.
You can also use hashmap to associate the values of the array that is going to be sorted and the values of the other. After sorting, you can easily find the values of the second array using the first array's values as keys.
One way to do this is to first capture the sorting order then apply it to each individual data list. Here is an example that sorts two arrays without creating specifically designed objects to hold the data from each array or implementing your own sorting algorithm. In addition to the requirements of sorting, its time complexity is O(N) and requires two additional integer arrays of length N. N being the number of elements in each of your data arrays.
public static void main(String[] args) {
// Original data in multiple arrays
String[] letters = new String[] {"C","D","B","E","A"};
int[] numbers = new int[] {3,4,2,5,1};
// Array to hold the destination locations.
// Each element refers to the index of the element in the letters array
// that goes into that location.
// e.g.
// The case of [C, D, B, E, A], this array would contain [4, 2, 0, 1, 3].
// The 0-th element, 4, means that the 4th element in the source array (A)
// should end up in index 0.
Integer[] srcIndexes = new Integer[letters.length];
// Assign indexes
for (int i = 0; i < letters.length; ++i)
srcIndexes[i] = i;
// Sort the destination index array according to the letters array.
Arrays.sort(srcIndexes, (Integer a, Integer b) -> letters[a].compareTo(letters[b]));
// Array to hold the source locations.
// Each element refers to the index where the element in the letters array should go to.
// e.g.
// The case of [C, D, B, E, A], this array would contain [2, 3, 1, 4, 0].
// The 0-th element, 2, means that C should end up in index 2 of the resultant
// array (i.e. the destination index).
int[] dstIndexes = new int[letters.length];
for (int i = 0; i < letters.length; ++i) {
dstIndexes[srcIndexes[i]] = i;
}
// Iterate through the indexes to move the data in the data array into their resultant locations.
for (int srcIndex = 0; srcIndex < letters.length; ) {
int dstIndex = dstIndexes[srcIndex];
// Index is already in place.
if (srcIndex==dstIndex) {
++srcIndex;
continue;
}
// Swap elements in the source and destination indexes.
swap(dstIndexes, srcIndex, dstIndex); // Make sure to swap the indexes too.
swap(letters, srcIndex, dstIndex); // Swap elements in the letters array.
swap(numbers, srcIndex, dstIndex); // Swap elements in the numbers array.
}
System.out.println("Indexes : "+Arrays.toString(dstIndexes));
System.out.println("Letters : "+Arrays.toString(letters));
System.out.println("Numbers : "+Arrays.toString(numbers));
}
private static <T> void swap(T[] objArray, int i, int j) {
T tmp = objArray[i];
objArray[i] = objArray[j];
objArray[j] = tmp;
}
private static void swap(int[] intArray, int i, int j) {
int tmp = intArray[i];
intArray[i] = intArray[j];
intArray[j] = tmp;
}

Categories

Resources