简体   繁体   English

按升序对所有偶数进行排序,然后按集合中的降序对所有奇数进行排序

[英]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: 保存在Collection中的输出:

6 12 34 78 67 31 9 1 

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

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. 我实现了一个基于Jesper算法的比较器。

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. 干杯。

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

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. 如果您不需要自己实现整个排序算法,您可以使用Collections.sort(list, comparator) ,并且您需要提供自己的Comparator<Integer>实现,该实现比较数字并返回结果,数字按规则定义的顺序排序。

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). 如果第一个数是偶数而第二个数是奇数,则返回-1(因为偶数必须在奇数之前)。
  2. If first number is odd and second number is even, return 1 (because even numbers must come before odd numbers). 如果第一个数字是奇数而第二个数字是偶数,则返回1(因为偶数必须在奇数之前)。
  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). 如果两个数字都是偶数:比较两个数字,如果第一个<秒则返回-1,如果相等则返回0,如果第一个>秒则返回1(对偶数数字进行排序)。
  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). 如果两个数字都是奇数:比较两个数字,如果第一个<秒则返回1,如果相等则返回0,如果第一个>秒则返回-1(对奇数减号进行排序)。

If you have the numbers in an array instead of a List , then use Arrays.sort(array, comparator) . 如果您有数组而不是List ,那么使用Arrays.sort(array, comparator)

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. 我要做的是在我的Collection.sort调用中,我会检查数字mod 2( number%2 )是否为零然后我会做一个简单的compareTo否则我会做一个Integer.MAX_INT - oddNumber然后做一个相比于。 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. 以上只是sudo代码,不要过于字面意思,只是为了给你一个想法。

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". 如果所有数字都是正数,则可以将奇数乘以“-1”,进行标准排序,然后再将所有奇数乘以“-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. 总开销:除了选择的排序算法之外还有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

You can use one data structure which holds all the numbers and then, create two SortedSet s, one for odd and one for even. 您可以使用一个包含所有数字的数据结构,然后创建两个SortedSet ,一个用于奇数,一个用于偶数。 The sorted set can take a Comparator as a parameter which allows you to sort elements while you enter data. 排序集可以将Comparator作为参数,允许您在输入数据时对元素进行排序。

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 . 您还可以使用两个Lists替换已排序的集。 Once that you have added all the numbers, call Collections.sort() on the lists and then merge as before. 一旦你添加了所有数字,在列表上调用Collections.sort()然后像以前一样合并。

Ad1. AD1。 We need to create a Comparator<Tnteger> that works with this rules. 我们需要创建一个符合此规则的Comparator<Tnteger>

  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. AD2。 I do not understand. 我不明白。

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

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) (这就是数字除以2的原因)

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] [6,12,34,78,67,31,9,1]

in Java :- Best Approach, Minimum Complexity 在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);
    }
}

Output :- 输出: -

Enter Array Size : 10 输入数组大小:10

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM