Recently I faced a question in an interview and I was unable to make logic for this question. I have an array like
[ 1,'a',45,'h',56,'d',2,'t',6,'p' ] . How to sort this array ? Output should be in this manner..
intArray = [1,2,6,45,56]
charArray= ['a','d','h','p','t']
If anybody knows its logic please comment. It would be a great help.
Thanks !
One way would be separate the integers and then sort-
Object[] objects = new Object[]{ 1,'a',45,'h',56,'d',2,'t',6,'p' };
List integers = new ArrayList<Integer>();
List characters = new ArrayList<Character>();
// Check and store integers and characters
// Doesn't validate and assumes you either have integers or characters
for(Object o : objects){
if(o instanceof Integer){
integers.add(o);
} else {
characters.add(o);
}
}
//Sort them separately
Collections.sort(integers);
Collections.sort(characters);
System.out.println(integers);
System.out.println(characters);
First of all separate the integers and character into different
arrays by checking its instance type.
If characters are stored in ASCII form (in java it is stored in ASCII form) you can directly sort them using any of the sorting algorithm, treating each value as integer only.
Similarly you can apply any sorting algorithm on integer array.
The following code produces desired result:
import static java.util.stream.Collectors.*;
final Map<Class<?>, Set<Object>> result = Stream.of(array) //
.collect(//
groupingBy(x -> x.getClass(), //
mapping(x -> x, toCollection(TreeSet::new))));
to view results:
System.out.println(Arrays.toString(result.get(Integer.class).toArray()));
System.out.println(Arrays.toString(result.get(Character.class).toArray()));
Below is the implementation of it. I have used two for loops so that we can easily find out the length of the two new subarrays instead of initializing it with the base array;s length.
I have tried not to use any in-built methods except Arrays.sort(). You can also write your own code to sort these two sub arrays.
public static void main(String[] args) {
Object[] array = { 1, 'a', 2, 'f', 5, 'b', 3 };
int intLoc = 0;
int charLoc = 0;
for (int i = 0; i < array.length; i++) {
if (array[i] instanceof Integer) {
intLoc++;
} else {
charLoc++;
}
}
int intArray[] = new int[intLoc];
char charArray[] = new char[charLoc];
for (int i = 0; i < array.length; i++) {
if (array[i] instanceof Integer) {
--intLoc;
intArray[intLoc] = (int) array[i];
} else {
--charLoc;
charArray[charLoc] = (char) array[i];
}
}
Arrays.sort(intArray);
Arrays.sort(charArray);
System.out.println(Arrays.toString(intArray));
System.out.println(Arrays.toString(charArray));
}
Related
I'm learning and understanding Java now, and while practising with arrays I had a doubt. I wrote the following code as an example:
class example
{
public static void main(String args[])
{
String a[] = new String[] {"Sam", "Claudia", "Josh", "Toby", "Donna"};
int b[] = new int[] {1, 2, 3, 4, 5};
for(int n=0;n<5;n++)
{
System.out.print (a[n] + "...");
System.out.println (b[n]);
}
System.out.println (" ");
java.util.Arrays.sort(a);
for(int n=0;n<5;n++)
{
System.out.print (a[n] + "...");
System.out.println (b[n]);
}
}
In a nutshell, this class created two arrays with five spaces each. It fills one with names of characters from the West Wing, and fills the other with numbering from one to five. We can say that the data in these two strings corresponds to each other.
Now, the program sorts the array with the names in it using Arrays.sort(). After printing the array again, you can see that while the names are now in alphabetical order, the numbers do not correspond anymore as the second array is unchanged.
How can I shuffle the contents of the second array to match the sort requirements of the first? The solution must also be flexible to allow for changes in the scope and size of the program. Please do not post any answers asking me to change my methodology with the arrays, or propose a more 'efficient' way of doing things. This is for educational purposed and I'd like a straight solution to the example code provided. Thanks in advance!
EDIT: I do NOT want to create an additional class, however I think some form of sorting through nested loops might be an option instead of Arrays.sort().
Below is the code without using any Map Collection, but if you want to use Map then it becomes very easy. Add both the arrays into map and sort it.
public static void main(String args[]) {
String a[] = new String[] {
"Sam", "Claudia", "Josh", "Toby", "Donna"
};
int b[] = new int[] {
1, 2, 3, 4, 5
};
for (int n = 0; n < 5; n++) {
System.out.print(a[n] + "...");
System.out.println(b[n]);
}
System.out.println(" ");
//java.util.Arrays.sort(a);
/* Bubble Sort */
for (int n = 0; n < 5; n++) {
for (int m = 0; m < 4 - n; m++) {
if ((a[m].compareTo(a[m + 1])) > 0) {
String swapString = a[m];
a[m] = a[m + 1];
a[m + 1] = swapString;
int swapInt = b[m];
b[m] = b[m + 1];
b[m + 1] = swapInt;
}
}
}
for (int n = 0; n < 5; n++) {
System.out.print(a[n] + "...");
System.out.println(b[n]);
}
}
Some people propose making a product type. That is feasible only if the amount of elements is small. By introducing another object you add object overhead (30+ bytes) for each element and a performance penalty of a pointer (also worsening cache locality).
Solution without object overhead
Make a third array. Fill it with indices from 0 to size-1. Sort this array with comparator function polling into the array according to which you want to sort.
Finally, reorder the elements in both arrays according to indices.
Alternative solution
Write the sorting algorithm yourself. This is not ideal, because you might make a mistake and the sorting efficiency might be subpar.
You have to ZIP your two arrays into an array which elements are instances of a class like:
class NameNumber
{
public NameNumber(String name, int n) {
this.name = name;
this.number = n;
}
public String name;
public int number;
}
And sort that array with a custom comparator.
Your code should be something like:
NameNumber [] zip = new NameNumber[Math.min(a.length,b.length)];
for(int i = 0; i < zip.length; i++)
{
zip[i] = new NameNumber(a[i],b[i]);
}
Arrays.sort(zip, new Comparator<NameNumber>() {
#Override
public int compare(NameNumber o1, NameNumber o2) {
return Integer.compare(o1.number, o2.number);
}
});
You should not have two parallel arrays. Instead, you should have a single array of WestWingCharacter objects, where each object would have a field name and a field number.
Sorting this array by number of by name would then be a piece of cake:
Collections.sort(characters, new Comparator<WestWingCharacter>() {
#Override
public int compare(WestWingCharacter c1, WestWingCharacter c2) {
return c1.getName().compareTo(c2.getName();
}
});
or, with Java 8:
Collections.sort(characters, Comparator.comparing(WestWingCharacter::getName));
Java is an OO language, and you should thus use objects.
What you want is not possible because you don't know internally how Arrays.sort swap the elements in your String array, so there is no way to swap accordingly the elements in the int array.
You should create a class that contains the String name and the int position as parameter and then sort this class only with the name, providing a custom comparator to Arrays.sort.
If you want to keep your current code (with 2 arrays, but this not the ideal solution), don't use Arrays.sort and implement your own sorting algorithm. When you swap two names, get the index of them and swap the two integers in the other array accordingly.
Here is the answer for your query.
public class Main {
public static void main(String args[]){
String name[] = new String[] {"Sam", "Claudia", "Josh", "Toby", "Donna"};
int id[] = new int[] {1, 2, 3, 4, 5};
for ( int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
int dtmp=0;
String stmp=null;
if (id[i] > id[j]) {
dtmp = rate[i];
id[i] = id[j];
id[j] = dtmp;
stmp = name[i];
name[i]=name[j];
name[j]=stmp;
}
}
}
System.out.println("Details are :");
for(int i=0;i<n;i++){
System.out.println(name[i]+" - "+id[i]);
}
}
}
The same solution, as a function that can be added to some utils class:
public static final boolean INCREASING = true;
public static final boolean DECREASING = false;
#SuppressWarnings("unchecked")
public static <T extends Comparable, U extends Object> void bubbleSort(ArrayList<T> list1, ArrayList<U>list2, boolean order) {
int cmpResult = (order ? 1 : -1);
for (int i = 0; i < list1.size() - 1; i++) {
for (int j = 0; j <= i; j++) {
if (list1.get(j).compareTo(list1.get(j+1)) == cmpResult) {
T tempComparable = list1.get(j);
list1.set(j , list1.get(j + 1));
list1.set(j + 1 , tempComparable);
U tempObject = list2.get(j);
list2.set(j , list2.get(j + 1));
list2.set(j + 1 , tempObject);
}
}
}
}
The arrays are not linked in any way. Like someone pointed out take a look at
SortedMap http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html
TreeMap http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
import java.util.*;
class mergeArrays2
{
public static void main(String args[])
{
String a1[]={"Sam", "Claudia", "Josh", "Toby", "Donna"};
Integer a2[]={11, 2, 31, 24, 5};
ArrayList ar1=new ArrayList(Arrays.asList(a1));
Collections.sort(ar1);
ArrayList ar2=new ArrayList(Arrays.asList(a2));
Collections.sort(ar2);
System.out.println("array list"+ar1+ " "+ar2);
}
}
i have two lists
array A = [1,3,5]//jst array A
list B = [3,7]//ArrayList B
i want 7 out from list B
for(int A=0;A<elements.length;A++){
for(int r=0;r<B.size();r++){
if(A[k] != B.get(r)){
pln(A[k]);
}
}
}
This should do it quickly:
B.retainAll(Arrays.asList(elements));
Assuming B is a List, and elements - an array.
Make the outer loop iterate over the list (B) and check for each element of B, if it is a member of the array. It's simply the other way round.
// for each element of B ...
for (i = 0; i < B.size(); i++ ) {
// ... check each element of A
for (j = 0; j < A.length; j++) {
// if it is equal.
if (B.get(i) == A[j]) {
// if yes, continue with the next B
break;
}
}
// so none of the elements of A matched the element of B.
System.out.println(B.get(i));
}
Note: the variable names violate java conventions. I only kept your names to help you understand the answer. Please use spelling names that that start with lower case characters. The Commodore 64 Basic times are over
Here's one way. Not the cleanest but it works:
final Integer[] arr1 = new Integer[] { 3, 4, 5 };
final Integer[] arr2 = new Integer[] { 3, 7 };
List<Integer> arr2List = new ArrayList<Integer>(Arrays.asList(arr2));
arr2List.retainAll(Arrays.asList(arr1));
System.out.println(arr2List); // output [3]
import java.util.ArrayList;
public class test1 {
public static void main(String[] args)
{
ArrayList<Integer> a1 = new ArrayList();
a1.add(3);
a1.add(4);
a1.add(5);
ArrayList<Integer> a2 = new ArrayList();
a2.add(3);
a2.add(7);
a2.retainAll(a1);
for(Integer i:a2)
{
System.out.println(i);
}
}
}
I know most people don't like writing methods for people but i was hoping someone could help me convert my algorithm into Java code. I hope my algorithm is good and actually works.
Sort a given array of ints into ascending order. Set Group Limit to 15 (that means that the sum of the group is not greater than 15).
Take the first element of the sorted array and insert into a Group (new array/list) eg. Group A.
Take the second element of the sorted array and insert unless it will make it exceed the group limit. If it exceeds, create a new Group B and insert there.
Take third element and try to insert into next available group.
Repeat until all ints have been checked and grouped.
Input:
egArray = [1,3,4,6,6,9,12,14]
Output:
Group A: [1,3,4,6], Group B: [6,9], Group C: [12], Group D: [14]
I have tried to do this, but failed epically, not even worth me posting my code. :-(
This is an example data and an algorithm I've made up for self learning, so please keep the criticism to a minimum. I genuinely learn from a lot of Stackoverflow posts people have written over the last few months, unfortunately I couldn't find one like this example. Thanks.
Try this:
public static void main(String[] arguments) {
int limit = 15;
int[] egArray = new int[] { 14, 1, 3, 4, 6, 6, 9, 12 };
ArrayList<ArrayList<Integer>> a = grouping(limit, egArray);
System.out.println(a);
}
public static ArrayList<ArrayList<Integer>> grouping(int limit, int[] array) {
// Sort the input array.
Arrays.sort(array);
// Copy the int[] to an ArrayList<Integer>
ArrayList<Integer> input = new ArrayList<>();
for (int i = 0; i < array.length; i++) {
input.add(array[i]);
}
// Initialize the groups
ArrayList<ArrayList<Integer>> groups = new ArrayList<>();
groups.add(new ArrayList<Integer>());
// Initialize the sums of the groups, to increase performance (I guess).
ArrayList<Integer> sums = new ArrayList<>();
sums.add(0);
// Iterate through the input array until there is no number
// left in it (that means we just added all the numbers
// into our groups array).
while (!input.isEmpty()) {
int n = input.get(0); // Store the number to 'n', to shortcut.
if (n > limit) {
String msg = "number is greater than the limit; cannot add number";
throw new IllegalArgumentException(msg);
// Or whatever to do if the number is larger than the limit.
}
boolean match = false;
// Search the next groups and check if our current
// number ('n') fits.
for (int i = 0; i < sums.size(); i++) {
if (sums.get(i) + n <= limit) {
// If it fits, then add the number to the group.
sums.set(i, sums.get(i) + n);
groups.get(i).add(n);
match = true;
break;
}
}
// If 'n' doesn't fit in any group, create a new one.
if (!match) {
ArrayList<Integer> e = new ArrayList<>();
e.add(n);
groups.add(e);
sums.add(n);
}
// Remove our number.
input.remove(0);
}
return groups;
}
Notice that the method returns an ArrayList<ArrayList<Integer>> instead of an int[][], but the effect is the same. In order to check the values of the groups, just run the main(String).
How about this method?
public static ArrayList group(ArrayList<Integer> arr, Integer groupLimit) {
ArrayList<ArrayList> result = new ArrayList<ArrayList>();
ArrayList<Integer> temp = new ArrayList<Integer>();
for (Integer x : arr) {
if (sumElements(temp) + x < groupLimit) {
temp.add(x);
} else {
result.add(temp);
temp = new ArrayList<Integer>();
temp.add(x);
}
}
if (temp.size() > 0) {
result.add(temp);
}
return result;
}
public static int sumElements(ArrayList<Integer> arr) {
Integer result = 0;
for(Integer x:arr) result += x;
return result;
}
I am trying to work out the best way to generate all possible permutations for a sequence which is a fixed number of digits and each digit has a different alphabet.
I have a number of integer arrays and each one can have different length and when generating the permutations only the values of the array can occupy the position in the final results.
A specific example is an int array called conditions with the following data:
conditions1 = {1,2,3,4}
conditions2 = {1,2,3}
conditions3 = {1,2,3}
conditions4 = {1,2}
conditions5 = {1,2}
and I want to create a 5 column table of all the possible permutations - this case 144 (4x3x3x2x2). Column 1 can only use the values from conditions1 and column 2 from conditions2, etc.
output would be :
1,1,1,1,1
1,1,1,1,2
1,1,1,2,1
1,1,1,2,2
1,1,2,1,1
.
.
through to
4,3,3,2,2
It's been too long since since I've done any of this stuff and most of the information I've found relates to permutations with the same alphabet for all fields. I can use that then run a test after removing all the permutations that have columns with invalid values but sounds inefficient.
I'd appreciate any help here.
Z.
Look ma, no recursion needed.
Iterator<int[]> permutations(final int[]... conditions) {
int productLengths = 1;
for (int[] arr : conditions) { productLengths *= arr.length; }
final int nPermutations = productLengths;
return new Iterator<int[]>() {
int index = 0;
public boolean hasNext() { return index < nPermutations; }
public int[] next() {
if (index == nPermutations) { throw new NoSuchElementException(); }
int[] out = new int[conditions.length];
for (int i = out.length, x = index; --i >= 0;) {
int[] arr = conditions[i];
out[i] = arr[x % arr.length];
x /= arr.length;
}
++index;
return out;
}
public void remove() { throw new UnsupportedOperationException(); }
};
}
Wrapping it in an Iterable<int[]> will make it easier to use with a for (... : ...) loop. You can get rid of the array allocation by doing away with the iterator interface and just taking in as argument an array to fill.
I have array of ValueA and ValueB(int type) . I am reading each value from array using a for loop.
I want to concatenate all there values in a single String. these value should be in the form of like these
ValueA1":"valueB1"|"ValueA2":"valueB2"|"ValueA3":"valueB3"|"ValueA4":"valueB4"|"....
I want this in Java, please can some ne help me with code..
You could try something like this
int[] valueA = methodWhichFillsA();
int[] valueB = methodWhichFillsB();
StringBuilder sb = new StringBuilder();
int maxSize = Math.max(valueA.length, valueB.length);
for(int i = 0; i < maxSize; i++){
if(i > 0)
sb.append("|");
if(i < valueA.length)
sb.append(valueA[i]);
sb.append(":");
if(i < valueB.length)
sb.append(valueB[i]);
}
System.out.println(sb.toString());
This will evaluate the size of the biggest array between valueA and valueB, loop on this size. If the element exists it's printed.
The first if is used to add the separator, if it's the first iteration no need for a "|"
Assuming the arrays are of different size, this solution will zip them together up until the end of the shorter array:
StringBuilder sb = new StringBuilder();
for(int i = 0; i < Math.min(arr1.length, arr2.length); i++){
sb.append( arr1[i] ).append("\":\"").append( arr2[i] ).append("\"|\"");
}
System.out.println(sb.toString());
Just a different way of doing it, this uses Guava
private String test(int[] a, int[] b) {
List<Integer> al = Lists.newArrayList();
List<Integer> bl = Lists.newArrayList();
for (Integer ai : a) {
al.add(ai);
}
for (Integer bi : b) {
bl.add(bi);
}
List<String> sets = Lists.newArrayList();
Iterator<Integer> itera = al.iterator();
Iterator<Integer> iterb = bl.iterator();
while(itera.hasNext() && iterb.hasNext()) {
sets.add(itera.next()+":"+iterb.next());
}
return Joiner.on("|").join(sets);
}
I was surprised to find no primitive array to list methods. If you can think of an elegant way to do that besides pulling it out into another method, the this code could be made cleaner.