Сортировка массивов в Java - PullRequest
4 голосов
/ 07 июня 2010

Написать статический метод в Java:

public static void sortByFour (int[] arr)

Получает в качестве параметра массив, полный неотрицательных чисел (ноль или плюс), и сортирует массив следующим образом:

  • В начале массива появятся все числа, которые делятся на четыре.

  • После них появятся все числа в массиве, которые делятся на 4 с остатком 1.

  • После них появятся все числа в массиве, которые делятся на 4 с остатком 2.

  • В конце массива появятся все остальные числа (те, которые делятся на 4 с остатком 3).

(Порядок чисел в каждой группе не имеет значения.)

Метод должен быть максимально эффективным.

Вот то, что я написал, но, к сожалению, это не работает хорошо ...: (

public static void swap( int[] arr, int left, int right )
{
    int temp = arr[left];
    arr[left] = arr[right];
    arr[right] = temp;
}

public static void sortByFour( int[] arr )
{
    int left = 0;
    int right = ( arr.length - 1 );
    int mid = ( arr.length / 2 );
    while ( left < right )
    {
        if ( ( arr[left] % 4 ) > ( arr[right] % 4 ) )
        {
            swap( arr, left, right );
            right--;
        }
        if ( ( arr[left] % 4 ) == ( arr[right] % 4 ) )
            left++;
        else
            left++;
    }
}

Как мне исправить или переписать мой код, чтобы он работал хорошо?

Ответы [ 6 ]

2 голосов
/ 08 июня 2010

Линейное решение

Наиболее асимптотически эффективный способ сделать это - использовать сортировку сегментов .

  • У вас есть 4 сегмента, одиндля каждого из классов конгруэнтности чисел по модулю 4.
  • Сканирование чисел в массиве один раз
    • Поместить каждое число в правильное ведро
  • Тогдапостроить выходной массив
    • Сначала поставить все числа из сегмента 0, затем все из сегмента 1, затем сегмента 2, затем сегмента 3

Таким образом, это сортируетчисла в O(N), что является оптимальным.Ключевым моментом здесь является то, что сортировка по числам по модулю 4 позволяет отсортировать только 4 числа: 0, 1, 2, 3.


Иллюстративное решение с List

Вот реализация вышеупомянутого алгоритма (для общего по модулю M), использующего List и для каждого для ясности.Не обращайте внимания на непроверенное предупреждение о приведении, просто сконцентрируйтесь на понимании алгоритма.

import java.util.*;

public class BucketModulo {
    public static void main(String[] args) {
        final int M = 4;
        List<Integer> nums = Arrays.asList(13,7,42,1,6,8,1,4,9,12,11,5);
        List<Integer>[] buckets = (List<Integer>[]) new List[M];
        for (int i = 0; i < M; i++) {
            buckets[i] = new ArrayList<Integer>();
        }
        for (int num : nums) {
            buckets[num % M].add(num);
        }
        nums = new ArrayList<Integer>();
        for (List<Integer> bucket : buckets) {
            nums.addAll(bucket);
        }
        System.out.println(nums);
        // prints "[8, 4, 12, 13, 1, 1, 9, 5, 42, 6, 7, 11]"
    }
}

Как только вы полностью поймете алгоритм, перевод его для использования массивов (если необходимо) будет тривиальным.


Специальное примечание по %

Условие, что числанеотрицательный является существенным, потому что % НЕ является оператором по модулю , поскольку он математически определен;это оператор Остаток .

System.out.println(-1 % 2); // prints "-1"

Ссылки

2 голосов
/ 08 июня 2010

Я повторю то, что сказал Дэниел: у вас есть выбор алгоритма сортировки.Используйте самый эффективный, который вы когда-либо рассматривали в классе, если это требование.Но когда вы дойдете до точки в вашем алгоритме, где сравниваются два элемента, сравните их значение mod 4.Так что-то вроде if A[i] > A[j] становится if A[i] % 4 > if A[j] % 4.Затем вы продолжаете делать то, что алгоритм указывает, что вы делаете с этим элементом массива.Поменяйте его, перепутайте, верните, все, что вам нужно.

Что касается кода, который вы опубликовали, я не думаю, что он поддается быстрому исправлению.Какой алгоритм он должен использовать?Для чего mid?Я думаю, что как только вы узнаете, какой алгоритм вы намереваетесь использовать, и выясните, какая строка кода содержит сравнение, вы сможете быстро увидеть и закодировать решение.

В общем, с такими вещамиЭто может помочь, если вы сосредоточитесь на получении рабочего решения до , когда вы беспокоитесь об эффективности.Я использовал сортировку выбора в первый раз, когда мне пришлось сделать такую ​​задачу.Я бы порекомендовал сначала попробовать это, а затем использовать полученный опыт для сортировки слиянием, которая равна O (n log n).

2 голосов
/ 08 июня 2010

Вы можете атаковать проблему следующим образом:

  1. Выберите алгоритм сортировки, который вы хотите использовать. Похоже, вы пытаетесь запрограммировать Быстрая сортировка , но вы также можете использовать Bubble Sort .
  2. Определите точку (и) алгоритма, где сравниваются два значения из входного массива. Например, в псевдокоде для Bubble Sort статьи Wikipedia единственное сравнение - строка if A[i] > A[i+1] then....
  3. Найдите способ сравнить два числа так, чтобы число s , имеющее остаток 0 при делении на 4, считалось меньше числа t , имеющего остаток 1 при делении на 4 Замените операции сравнения алгоритма вычислением компаратора (например, if myIsGreater(A[i], A[i+1]) then...).

На шаге 3 вы определенно на правильном пути, если учесть оператор модуля.

2 голосов
/ 07 июня 2010

Я сделаю это в psuedocode для вас, но если вы сделаете это в коде, вы получите ответ, и это домашнее задание, чтобы вы могли выполнять свою собственную работу. = Р * * тысяча одна

Вот как это сделать без списков. Этот пример ограничен в зависимости от требований, но будет работать после того, как вы его закодируете.

int bucketSize = (arr.length() / 4) + 1;

int bucket1[bucketSize];
int bucket2[bucketSize];
int bucket3[bucketSize];
int bucket4[bucketSize];

for (int i=0; i<arr.length; i++) {
    if ((arr[i] % 4) == 0)
        put arr[i] in bucket 1
    else if ((arr[i] % 4) == 1)
        put arr[i] in bucket 2
    else if ((arr[i] % 4) == 2)
        put arr[i] in bucket 3
    else
        put arr[i] in bucket 4
}

for (int i=0; i<4; i++) {
    this will go for each bucket
    for (int j=0; j<bucketSize; j++) {
        do sort of your choice here to sort the given bucket
        the sort you used in your code will do fine (the swapping)
    }
}

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

1 голос
/ 19 июня 2010

Вот способ на языке Java ...

    Arrays.sort(arr,new Comparator<Integer>(){
      public int compare(Integer a,Integer b)
      {
        return (a % 4) - (b % 4);
      }
    });
1 голос
/ 07 июня 2010

Прочитайте эту страницу.http://en.wikipedia.org/wiki/Sorting_algorithm#Summaries_of_popular_sorting_algorithms

Это должно помочь вам лучше всего в долгосрочной перспективе.Это тоже довольно весело!

...