Jayy
Jayy

Reputation: 2436

Sort all even numbers in ascending order and then sort all odd numbers in descending order in a collection

This is an interview question.

There are some random numbers given (let's say in an integer array).

  1. How can we sort all the even numbers in ascending order first and then sort all the odd numbers in descending order.
  2. which Collection suits best.

Input numbers:

12 67 1 34 9 78 6 31

Output saved in Collection:

6 12 34 78 67 31 9 1 

Upvotes: 7

Views: 22170

Answers (13)

VIKASH SINHA
VIKASH SINHA

Reputation: 250

package com.java.util.collection;

import java.util.Arrays;
import java.util.Collections;

public class EvenOddSorting {

    public static void eventOddSort(int[] arr) {
        int i =0;
        int j =arr.length-1;
        while(i<j) {
            if(isEven(arr[i]) && isOdd(arr[j])) {
                i++;
                j--;
            } else if(!isEven(arr[i]) && !isOdd(arr[j])) {
                swap(i,j,arr);
            } else if(isEven(arr[i])){
                i++;
            } else{
                j--;
            }

        }   
        display(arr);
        // even number sorting
        Arrays.sort(arr,0,i);
        insertionSort(arr,i,arr.length);
        // odd number sorting
        display(arr);

    }

    /**
     * Instead of insertion sort, you can use merge or quick sort.
     * @param arr
     * @param firstIndex
     * @param lastIndex
     */
    public static void insertionSort(int[] arr, int firstIndex, int lastIndex){
        for(int i=firstIndex+1;i<lastIndex;i++){
            int key =arr[i];
            int j=i-1;
            while(j>=firstIndex  && key > arr[j]) {
                arr[j+1] = arr[j];
                arr[j] =key;
                j=j-1;
            }
            System.out.println("\nAfter "+(i+1) +"  Iteration : ");
            display(arr);
        }
    }

    public static void display(int[] arr) {
        System.out.println("\n");
        for(int val:arr){
            System.out.print(val +"  ");
        }
    }

    private static void swap(int pos1, int pos2, int[] arr) {
        int temp = arr[pos1];
        arr[pos1]= arr[pos2];
        arr[pos2]= temp;
    }

    public static boolean isOdd(int i) {
        return (i & 1) != 0;
    }
    public static boolean isEven(int i) {
        return (i & 1) == 0;
    }
    public static void main(String[] args) {
        int arr[]={12, 67, 1, 34, 9, 78, 6, 31};
        eventOddSort(arr);
    }
}

Upvotes: 1

Abhishek Anand
Abhishek Anand

Reputation: 1

in Java :- Best Approach, Minimum Complexity

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Scanner;

public class EvenOddSorting {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int i, size;
        ArrayList<Integer> listEven = new ArrayList<Integer>();
        ArrayList<Integer> listOdd = new ArrayList<Integer>();
        ArrayList<Integer> finalList = new ArrayList<Integer>();
        Scanner sc = new Scanner(System.in);
        System.out.println("Enter Array Size : ");
        size = sc.nextInt();
        int A[] = new int[size];
        for (i = 0; i < size; i++) {
            A[i] = sc.nextInt();
        }
        for (i = 0; i < size; i++){
            if (A[i] % 2 == 0){
                listEven.add(A[i]);
            }
            else if (A[i] % 2 != 0) {
                listOdd.add(A[i]);
            }
        }
        Collections.sort(listEven);
        Collections.sort(listOdd);
        Collections.reverse(listOdd);
        finalList.addAll(listOdd);
        finalList.addAll(listEven);
        System.out.println("Result is : "+finalList);
    }
}

Output :-

Enter Array Size : 10

1 2 3 4 5 6 7 8 9 10 Result is : [9, 7, 5, 3, 1, 2, 4, 6, 8, 10]

Upvotes: -1

ayan_2587
ayan_2587

Reputation: 11

Here's the code :

@Override
public int compare(Integer o1, Integer o2) {
    if (o1 % 2 ==0) 
    {
        if (o2 % 2 == 0)
        {
            if (o1 < o2)
                return -1;
            else
                return 1;
        }
        //if (o2 % 2 != 0)
        else
        {
            return -1;
        }
    }
    else 
    {
        if (o2 % 2 != 0)
        {
            if (o1 < o2)
                return 1;
            else
                return -1;
        }
        //if (o2 % 2 == 0)
        else
        {
            return 1;
        }
    }
}

Upvotes: 1

bchetty
bchetty

Reputation: 2241

I just coded a fast example, as below:

public class CustomSorting {
    public static void main(String[] args) {
        Integer[] intArray = new Integer[] {12, 67, 1, 34, 9, 78, 6, 31};
        Arrays.sort(intArray, new Comparator() {
            @Override
            public int compare(Object obj1, Object obj2) {
                Integer int1 = (Integer) obj1;
                Integer int2 = (Integer) obj2;

                int mod1 = Math.abs(int1%2);
                int mod2 = Math.abs(int2%2);

                return ((mod1 == mod2) ? ((mod1 == 0) ? int1.compareTo(int2) : int2.compareTo(int1)) : ((mod1 < mod2) ? -1 : 1));
            }
        });
    }
}

Output:

[6, 12, 34, 78, 67, 31, 9, 1]

Upvotes: 0

phil
phil

Reputation: 1

Like this:

var list = new List<int>{1,5,2,6,3,9,10,11,12};

var sorted = list.Where (l => l%2 ==0).OrderBy (l=>l).Union(list.Where (l => l%2 != 0).OrderByDescending (l=>l));

Upvotes: 0

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726599

Any collection that supports sorting with a custom comparer will do - even an array. Implement your custom comparator as follows:

public int compare(int x, int y) {
    if (x&1 == y&1) {
        // Both numbers are odd or both numbers are even
        if (x&1 == 0) {
            // Both numbers are even: compare as usual
            return Integer.compare(x, y);
        } else {
            // Both numbers are odd: compare in reverse
            return Integer.compare(y, x);
        }
    }
    // One is odd, the other one is even
    if (x&1 == 0) {
        return -1;
    }
    return 1;
}

Upvotes: 12

Peter Lawrey
Peter Lawrey

Reputation: 533530

I would normalise all the numbers and then sort them.

public static void main(String[] args) {
    int[] values = {Integer.MIN_VALUE, 0, Integer.MAX_VALUE - 1, Integer.MIN_VALUE + 1, -1, 1, Integer.MAX_VALUE};
    for (int i = 0; i < values.length; i++) {
        int value = encode(values[i]);
        assert decode(value) == values[i];
        values[i] = value;
    }
    Arrays.sort(values);
    for (int i = 0; i < values.length; i++)
        // give back the original value.
        values[i] = decode(values[i]);
    System.out.println(Arrays.toString(values));
}

private static int decode(int value) {
    return value >= 0
            ? Integer.MAX_VALUE - (value << 1)
            : Integer.MIN_VALUE + (value << 1);
}

private static int encode(int value) {
    return (value & 1) == 0
            ? (value >> 1) + Integer.MIN_VALUE / 2
            : Integer.MAX_VALUE / 2 - (value >> 1);
}

prints

[-2147483648, 0, 2147483646, 2147483647, 1, -1, -2147483647]

There is extra shifting here so very large numbers are not mangled. (which is why the number is divided by two)

Upvotes: 0

user670804
user670804

Reputation:

You could do as follows

public ArrayList<Integer> sort(Integer[] input) {
        int length = input.length;
        ArrayList<Integer> oddNumber = new ArrayList<Integer>(0);
        ArrayList<Integer> evenNumber = new ArrayList<Integer>(0);
        for (int i = 0; i < length; i++) {
            Integer val = input[i];
            if(isEven(val)){
                evenNumber.add(val);
            } else {
                oddNumber.add(val);
            }
        }
        Collections.sort(evenNumber);
        Collections.sort(oddNumber, Collections.reverseOrder());

        evenNumber.addAll(oddNumber);

        return evenNumber;
    }

    public boolean isEven(Integer x) {
        return x % 2 == 0;
    }

EDIT

I implemented a comparator based on Jesper algorithm.

public ArrayList<Integer> sort(Integer[] input) {
        ArrayList<Integer> output = new ArrayList<Integer>(0);
        output.addAll(Arrays.asList(input));

        Collections.sort(output, new EvenOddComparator());

        return output;
    }

    public class EvenOddComparator implements Comparator<Integer>
    {
        final int BEFORE = -1;
        final int EQUAL = 0;
        final int AFTER = 1;

        @Override
        public int compare(Integer o1, Integer o2) {
            if (o1 % 2 == 0 && o2 % 2 != 0) {
                return BEFORE;
            } else if (o1 % 2 != 0 && o2 % 2 == 0) {
                return AFTER;
            } else if (o1 % 2 == 0 && o2 % 2 == 0) {
                return o1.compareTo(o2);
            } else if (o1 % 2 != 0 && o2 % 2 != 0) {
                return o2.compareTo(o1);
            }
            return EQUAL;
        }

    }

Cheers.

Upvotes: 5

Ad1. We need to create a Comparator<Tnteger> that works with this rules.

  1. If we compare a even number with odd number then even is always greater.
  2. If we compare two odd number the result is as we would like to desc sort.
  3. If we compare two even number the result is as we would like to asc sort.

Ad2. I do not understand.

Upvotes: 0

Roman
Roman

Reputation: 66166

If all numbers are positive, you can multiply your odd numbers by "-1", do a standard sort, then again multiply all odd numbers by "-1".

If you want the order as in a question, you'll also have to swap "negative" and "positive" array parts before the 2nd multiplication.

Total overhead: 3 more loops in addition to a chosen sort algorithm.

List<Integer> numbers = new ArrayList<Integer>();
//add some numbers here
//12 67 1 34 9 78 6 31 <-- in the list
for (int i = 0; i < numbers.size(); i++) {
    if (numbers.get(i) % 2 == 1) {
       numbers.set(i, numbers.get(i) * (-1));
    }
}
//12 -67 -1 34 -9 78 6 -31 <-- before sort
sort(numbers);
//-67 -31 -9 -1 6 12 34 78 <-- after sort
swapNegativeAndPositiveParts(numbers);
//6 12 34 78 -67 -31 -9 -1 <-- after swap
for (int i = 0; i < numbers.size(); i++) {
    if (numbers.get(i) % 2 == 1) {
       numbers.set(i, numbers.get(i) * (-1));
    }
}
//6 12 34 78 67 31 9 1  <-- after second multiplication

Upvotes: 0

Jesper
Jesper

Reputation: 206816

If it is not required that you implement the whole sorting algorithm yourself, you could just use Collections.sort(list, comparator), and you'll need to supply your own Comparator<Integer> implementation that compares the numbers and returns a result so that the numbers are sorted in the order that is defined by the rules.

The comparator would have to implement these rules:

  1. If first number is even and second number is odd, return -1 (because even numbers must come before odd numbers).
  2. If first number is odd and second number is even, return 1 (because even numbers must come before odd numbers).
  3. If both numbers are even: Compare both numbers, return -1 if first < second, 0 if equal, 1 if first > second (sorts even numbers ascending).
  4. If both numbers are odd: Compare both numbers, return 1 if first < second, 0 if equal, -1 if first > second (sorts odd numbers descending).

If you have the numbers in an array instead of a List, then use Arrays.sort(array, comparator).

Upvotes: 2

npinti
npinti

Reputation: 52185

You can use one data structure which holds all the numbers and then, create two SortedSets, one for odd and one for even. The sorted set can take a Comparator as a parameter which allows you to sort elements while you enter data.

Once that you will have gone through all the numbers, create a new collection which merges the two sorted sets.

You can also replace the sorted sets by using two Lists. Once that you have added all the numbers, call Collections.sort() on the lists and then merge as before.

Upvotes: 0

Ali
Ali

Reputation: 12674

I dont think any one Collection is necessarily better than the other, I would use something that extends a list rather than a set though and definitely not a map.

What I would do is that in my Collection.sort call, I would check if the number mod 2 (number%2) is zero then I would would do a simple compareTo otherwise I would do an Integer.MAX_INT - oddNumber and then do a compareTo. That way the larger the odd number the smaller the generated number and it will be sorted to the end of the list in a descending order.

Integer num1 = (o1%2 == 0)? new Integer(o1) : new Integer(Integer.MAX_INT - o1);
Integer num2 = (o2%2 == 0)? new Integer(o2) : new Integer(Integer.MAX_INT - o2);
return num1.compareTo(num2);

Above is just sudo code, don't take it too literally, its just to give you an idea.

Upvotes: 0

Related Questions