首页 > 解决方案 > 在单词列表上实现合并排序 - 原始单词附加回列表?

问题描述

我正在尝试在 size 的字符串列表上实现合并排序算法N,并且我已经设法对其进行排序,但由于某种原因,原始值被添加到排序列表的末尾。

我对实现排序算法很陌生(阅读:非常新),所以如果我错过了什么,我真的很感激有人告诉我。

    public static void mergeSortWords(int n, List<String> words) {

        if (n < 2) {
            return;
        }

        int mid = n / 2; // Getting the mid-point of the array

        List<String> l = new ArrayList<String>(mid); // Left side of array
        List<String> r = new ArrayList<String>(n-mid); // Right side of array

        for (int i = 0; i < mid; i++) {
            l.add(i, words.get(i));
        }

        for (int j = mid; j < n; j++) {
            r.add(j - mid, words.get(j));
        }


        mergeSortWords(mid, l); // recursively sort the left side
        mergeSortWords(n-mid, r); // recursively sort the right side

        mergeWords(n, words, l, r, mid, n-mid); // merge the sorted arrays back together
    }

    public static void mergeWords(int n, List<String> words, List<String> l, List<String> r, int left, int right) {

        if (words.size() > n) {
            return;
        }

        int i = 0, j = 0, k = 0;

        while (i < left && j < right) {

            if (l.get(i).compareToIgnoreCase(r.get(j)) < 0) { // comparing the strings alphabetically
                words.add(k++, l.get(i++));
            }
            else {
                words.add(k++, r.get(j++));
            }
        }

        while (i < left) {
            words.add(k++, l.get(i++));
        }
        while (j < right) {
            words.add(k++, r.get(j++));
        }
    }

我像这样进行单元测试:

    @Test
    public void mergeSortWordsTest() {

        List<String> actual = new ArrayList<String>();
        List<String> expected = new ArrayList<String>();

        actual.add("hello");
        actual.add("yo");
        actual.add("hi");
        actual.add("what");
        actual.add("bottle");

        expected.add("bottle");
        expected.add("hello");
        expected.add("hi");
        expected.add("what");
        expected.add("yo");

        mergeSortWords(actual.size(), actual);
        Assert.assertEquals(expected, actual);

我收到:

java.lang.AssertionError: 
Expected :[bottle, hello, hi, what, yo]
Actual   :[bottle, hello, hi, what, yo, hello, yo, hi, what, bottle]

感谢您的任何指点!

标签: javaalgorithmmergesort

解决方案


因为words您传递给的列表mergeWords永远不会被清除。mergeWords只会将新元素添加到此列表中,而不关心它已经包含的元素。简单地做一个

words.clear();

开始时mergeWords

.set(int index, E element)或者,您可以使用而不是覆盖现有元素.add()。但是您需要确保列表的大小正确。

一些无关的评论:

在您的函数调用中,您总是将列表的大小作为附加参数 ( n, left, right) 传递。这是多余的(您可以使用 获取大小list.size())。任何多余的东西很容易变得不一致(即,如果你传递了错误的大小会发生什么?)。所以最好去掉这些参数。

将元素添加到列表时,会使用重载add(int index, E element)。这很好,但我认为使用重载add(E element)更容易处理,因为您不需要跟踪添加元素的位置。重载只会将新元素附加到列表的末尾。


推荐阅读