Сортировать все четные числа в порядке возрастания, а затем сортировать все нечетные числа в порядке убывания в коллекции

Это вопрос интервью.

есть некоторые случайные числа, заданные (скажем, в целочисленном массиве).

  1. как мы можем сначала отсортировать все четные числа в порядке возрастания, а затем отсортировать все нечетные числа в порядке убывания.
  2. какая коллекция подходит лучше всего.

ввод чисел:

12 67 1 34 9 78 6 31

вывод сохранен в коллекции:

6 12 34 78 67 31 9 1 

13 ответов


любая коллекция, поддерживающая сортировку с помощью пользовательского компаратора, будет делать-даже массив. Реализуйте свой пользовательский компаратор следующим образом:

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;
}

вы можете сделать следующее

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;
    }

редактировать

я реализовал компаратор на основе алгоритма Йеспер.

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;
        }

    }

Ура.


если не требуется, чтобы вы реализовали весь алгоритм сортировки самостоятельно, вы можете просто использовать Collections.sort(list, comparator), и вам нужно будет предоставить свой собственный Comparator<Integer> реализация, которая сравнивает числа и возвращает результат, чтобы числа были отсортированы в порядке, определенном правилами.

компаратор должен был бы реализовать эти правила:

  1. если первое число четное, а второе нечетное, верните -1 (потому что четные числа должны быть перед нечетными числа.)
  2. если первое число нечетное, а второе четное, верните 1 (потому что четные числа должны предшествовать нечетным).
  3. если оба числа четные: сравните оба числа, верните -1, если первый второй (сортирует четные числа по возрастанию).
  4. если оба числа Нечетные: сравните оба числа, верните 1, Если first second (сортирует нечетные числа по убыванию).

если у вас есть числа в массиве вместо List, а затем использовать Arrays.sort(array, comparator).


вот код :

@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;
        }
    }
}

пакета com.Ява.утиль.коллекция;

импорт java.утиль.Матрицы; импорт java.утиль.Сборники;

публичный класс 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);
}

}


Я не думаю, что какая-либо одна коллекция обязательно лучше, чем другая, я бы использовал то, что расширяет список, а не набор, хотя и определенно не карту.

что бы я сделал, так это в моем Collection.sort вызов, я бы проверил, если номер mod 2 (number%2) равен нулю, тогда я бы сделал простой compareTo в противном случае я сделал бы Integer.MAX_INT - oddNumber а затем сделать compareTo. Таким образом, чем больше нечетное число, тем меньше сгенерированное число, и оно будет отсортировано до конца список в порядке убывания.

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);

выше-это просто код sudo, не принимайте это слишком буквально, просто чтобы дать вам идею.


вы можете использовать одну структуру данных, которая содержит все числа, а затем создайте два объект sortedsets, один для нечетных и один для четных. Сортированный набор может принимать Comparator в качестве параметра, который позволяет сортировать элементы при вводе данных.

как только вы пройдете через все числа, создайте новую коллекцию, которая объединяет два отсортированных набора.

вы также можете заменить сортированные наборы с помощью двух Lists. После того, как вы добавили все номера, звоните Collections.sort() в списках, а затем объединить, как и раньше.


Если все числа положительные, вы можете умножить свои нечетные числа на "-1", сделать стандартную сортировку, а затем снова умножить все нечетные числа на"-1".

Если вы хотите порядок, как в вопросе, вам также придется поменять местами "отрицательные" и "положительные" части массива перед 2-м умножением.

общие накладные расходы: еще 3 цикла в дополнение к выбранному алгоритму сортировки.

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

Ad1. Нам нужно создать Comparator<Tnteger> это работает с этими правилами.

  1. если мы сравниваем четное число с нечетным, то четное всегда больше.
  2. если мы сравним два нечетных числа, результат будет таким, как мы хотели бы сортировать desc.
  3. если мы сравним два четных числа, результат будет таким, как мы хотели бы сортировать asc.

Ad2. Я не понимаю.


Я бы нормализовал все числа, а затем отсортировал их.

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);
}

печать

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

здесь есть дополнительное смещение, поэтому очень большие числа не искажаются. (именно поэтому число делится на двоих)


такой:

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));

Я просто написала пример, как показано ниже:

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));
            }
        });
    }
}

выход:

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


в Java :- Лучший Подход, Минимальная Сложность

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);
    }
}

выход :-

Введите Размер Массива : 10

1 Два Три Четыре Пять Шесть Семь Восемь Девять Десять Результат : [9, 7, 5, 3, 1, 2, 4, 6, 8, 10]