【问题标题】:Sort Array based on number of character occurrences根据字符出现的数量对数组进行排序
【发布时间】:2013-10-07 18:13:14
【问题描述】:

假设我有一个这样的数组列表:

[24、15、55、101、555]

如何根据字符串中 "5" 的数量对数组进行排序?如果没有五,那么较小的数字先行。所以排序后的数组是:

[24,101,15,5,555]

知道怎么做吗?也许计算 5 次出现的次数并有一个 2d 数组,其中 1. 实际数字 2. 5 次出现次数?然后根据二维数组的第二列对数组进行排序?我是java新手,所以请多多包涵。

【问题讨论】:

  • 查看ComparableComparator 接口。
  • 至少试一试。如果您在 google 上键入标题,您将找到 100 个基于数组排序的答案。
  • 而且您不必使用二维数组,您可以在 compareTo 方法中实现整个逻辑。

标签: java arrays sorting multidimensional-array


【解决方案1】:

我将创建一个实现Comparator<String> interface 的类。在compare 方法中,检测那里的5 字符数。如果5 字符数相等,则使用Integer.parseInt 获取数字并进行比较。

如果第一个字符串应分别比较小于、等于或大于第二个字符串,请确保返回小于零、0 或大于零的数字,以履行compare 的合同。

int 比较(T o1, T o2)

比较它的两个参数的顺序。返回负整数、零或正整数,因为第一个参数是 小于、等于或大于秒。

然后拨打Arrays.sort(yourArray, new YourStringComparator());

【讨论】:

  • 我阅读了 Comparator 并想出了如何去做。谢谢!
【解决方案2】:

我会创建两个数组,一个包含不带 5 的数字,另一个包含带 5 的数字。

对两者进行排序并将第一个与第二个连接起来。

【讨论】:

  • 它会起作用,但我认为这不是一个好方法。应该改用Comparator
  • 如何根据出现次数为 5 的数组对数组进行排序?
【解决方案3】:

这是 (1) 一种非常有效的通用方法,以及 (2) 一种简单有效的方法。

(1) 在第一个排序中,我计算并缓存数组中每个值一次的数字 5 的出现次数。然后我使用通用排序方法根据缓存的值进行排序。这比自定义比较器要好,因为列表中的每个元素只计算一次出现的次数。

(2)在第二种排序中,我只是使用了一个自定义比较器,实现起来更简单。

排序 (3) 和 (4) 分别使用字符串而不是整数执行与 (1) 和 (2) 相同的操作。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;

public class DigitSort {
    public static void main(String[] args) {
        List<Integer> initInt = Arrays.asList(555, 55, 5, 101, 202);
        final int sortDigit = 5;

        // sort #1
        List<Integer> ints = new ArrayList<>(initInt);
        sort(ints, new ToComparable<Integer, DigitComparable>() {
            @Override                
            public DigitComparable toComparable(Integer number) {
                return number == null ? null : new DigitComparable(number, digitCount(sortDigit, number));
            }
        });
        System.out.println("Results of int generic sort:");
        for (Integer number : ints)
            System.out.println(number);

        // sort #2
        ints = new ArrayList<>(initInt);
        Collections.sort(ints, new Comparator<Integer>() {
            @Override
            public int compare(Integer number1, Integer number2) {
                if (number1 == null && number2 == null)
                    return 0;
                if (number1 == null)
                    return -1;
                if (number2 == null)
                    return 1;
                int digitCount1 = digitCount(sortDigit, number1);
                int digitCount2 = digitCount(sortDigit, number2);
                return
                    digitCount1 > 0 && digitCount2 > 0 ? digitCount1 - digitCount2 :
                    digitCount2 > 0 ? -1 :
                    digitCount1 > 0 ? 1 :
                    number1 - number2;
            }
        });
        System.out.println("\nResults of int comparator sort:");
        for (Integer number : ints)
            System.out.println(number);

        List<String> initString = new ArrayList<>(initInt.size());
        for (Integer number : initInt)
            initString.add(number == null ? null : number.toString());

        // sort #3
        List<String> strings = new ArrayList<>(initString);
        sort(strings, new ToComparable<String, DigitComparable>() {
            @Override                
            public DigitComparable toComparable(String number) {
                if (number == null)
                    return null;
                int asInt = Integer.parseInt(number);
                return new DigitComparable(asInt, digitCount(sortDigit, asInt));
            }
        });
        System.out.println("\nResults of string generic sort:");
        for (String number : strings)
            System.out.println(number);

        // sort #4
        strings = new ArrayList<>(initString);
        Collections.sort(strings, new Comparator<String>() {
            @Override
            public int compare(String number1, String number2) {
                if (number1 == null && number2 == null)
                    return 0;
                if (number1 == null)
                    return -1;
                if (number2 == null)
                    return 1;
                int digitCount1 = digitCount(sortDigit, number1);
                int digitCount2 = digitCount(sortDigit, number2);
                return
                    digitCount1 > 0 && digitCount2 > 0 ? digitCount1 - digitCount2 :
                    digitCount2 > 0 ? -1 :
                    digitCount1 > 0 ? 1 :
                    Integer.parseInt(number1) - Integer.parseInt(number2);
            }
        });
        System.out.println("\nResults of string comparator sort:");
        for (String number : strings)
            System.out.println(number);
    }

    private static class DigitComparable implements Comparable<DigitComparable> {
        private final int number, digitCount;

        DigitComparable(int number, int digitCount) {
            this.number = number;
            this.digitCount = digitCount;
        }

        @Override
        public int compareTo(DigitComparable other) {
            return
                digitCount > 0 && other.digitCount > 0 ? digitCount - other.digitCount :
                other.digitCount > 0 ? -1 :
                digitCount > 0 ? 1 :
                number - other.number;
        }
    }

    protected static int digitCount(int digit, String number) {
        char asChar = Character.forDigit(digit, 10);
        int count = 0;
        for (char c : number.toCharArray())
            if (c == asChar)
                ++count;
        return count;
    }

    protected static int digitCount(int digit, int number) {
        number = Math.abs(number);
        int count = 0;
        while (number != 0) {
            if (number % 10 == digit)
                ++count;
            number /= 10;
        }
        return count;
    }

    public interface ToComparable<T, C extends Comparable<? super C>> {
         C toComparable(T t);
    }

    public static <T, C extends Comparable<? super C>> void sort(List<T> list, ToComparable<T, C> function) {
       class Pair implements Comparable<Pair> {
          final T original;
          final C comparable;

          Pair(T original, C comparable) {
             this.original = original;
             this.comparable = comparable;
          }

          @Override
          public int compareTo(Pair other) {
                return
                  comparable == null && other.comparable == null ? 0 :
                  comparable == null ? -1 :
                  other.comparable == null ? 1 :
                  comparable.compareTo(other.comparable);
          }
       }

       List<Pair> pairs = new ArrayList<>(list.size());
       for (T original : list)
          pairs.add(new Pair(original, function.toComparable(original)));

       Collections.sort(pairs);

       ListIterator<T> iter = list.listIterator();
       for (Pair pair : pairs) {
          iter.next();
          iter.set(pair.original);
       }
    }
}

【讨论】:

    【解决方案4】:

    首先,我假设数组列表的元素是字符串。在那种情况下,我认为您的想法是正确的。我会使用 for each 循环遍历每个字符串并创建一个新的二维数组列表。基本上,数组的第一维包含每个字符串中 5 的数量,数组列表的第二维包含数字 0 到 n-1,n 是原始数组中的元素数。然后手动对数组的第一个维度进行排序,并将第二个数组的元素分别移动到它们的第一个维度对应部分。完成此操作后,您的第二个数组应包含原始数组应包含的元素的顺序。使用此第二个数组调整原始数组的顺序并将其返回。

    希望这会有所帮助。

    【讨论】:

    • 我认为学习现有的 Java 排序方法比从头开始编程要好。我敢打赌,Java 内部算法和它们的实现都非常出色。
    • 没错,但这听起来像是家庭作业,我不知道他被限制使用哪种材料。
    猜你喜欢
    • 2012-11-04
    • 1970-01-01
    • 2012-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多