Java基数排序知识点(含面试大厂题和源码)

基数排序(Radix Sort)是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。它通过从最低位(个位)开始排序,然后逐渐转向最高位,对每一位进行稳定的排序(使用计数排序或桶排序),从而达到整体排序的目的。

算法原理

基数排序的工作原理如下:

  1. 找出最大数的位数:确定排序的轮数,即从个位开始,到最大数的位数结束。
  2. 按位进行排序:从最低位(个位)开始,对每一位进行排序。可以使用计数排序或桶排序来完成这一步骤。
  3. 重复步骤:对每一位进行排序后,移动到下一位,重复排序过程,直到所有位数都被排序。

算法实现

以下是基数排序的Java实现示例:

java 复制代码
import java.util.Arrays;

public class RadixSortExample {
    public static void main(String[] args) {
        int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};
        radixSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void radixSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }

        // 找到最大数的位数
        int max = Arrays.stream(arr).max().getAsInt();
        int significantDigits = (int) Math.log10(max) + 1; // 以10为底的对数

        // 从个位开始,按位进行排序
        for (int i = 1; i <= significantDigits; i *= 10) {
            countingSortByDigit(arr, i);
        }
    }

    private static void countingSortByDigit(int[] arr, int digit) {
        int n = arr.length;
        int[] output = new int[n];
        int[] count = new int[10];

        // 计算频率数组
        for (int i = 0; i < n; i++) {
            int digitValue = (arr[i] / digit) % 10;
            count[digitValue]++;
        }

        // 累计频率
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 根据频率数组和当前位的值,放置到输出数组
        for (int i = n - 1; i >= 0; i--) {
            int digitValue = (arr[i] / digit) % 10;
            output[count[digitValue] - 1] = arr[i];
            count[digitValue]--;
        }

        // 将输出数组复制回原数组
        System.arraycopy(output, 0, arr, 0, n);
    }
}

算法适用性

基数排序适用于以下场景:

  1. 待排序数组中的元素是整数或可以转换为整数的字符串。
  2. 待排序数组中的元素位数固定或相差不大。

算法优缺点

优点:

  1. 基数排序可以实现线性时间复杂度 O(nk),其中 n 是待排序数组的长度,k 是最大数的位数。
  2. 基数排序是一种稳定的排序算法,相同元素的相对顺序保持不变。

缺点:

  1. 基数排序需要额外的空间来存储计数数组和输出数组。
  2. 当元素的位数非常大时,基数排序可能需要较长的预处理时间和额外空间。

通过理解和实践基数排序,你可以在面试中更好地展示你的算法能力和问题解决技巧。希望这些信息能够帮助你在面试中取得成功。

题目 1:实现基本的基数排序

描述 :

给定一个非负整数数组 arr,实现一个基数排序算法对其进行排序。

要求:

  • 不使用任何现成的排序库或函数。
  • 保持排序的稳定性。

示例 :

输入:[170, 45, 75, 90, 802, 24, 2, 66]

输出:[2, 24, 45, 66, 75, 90, 170, 802]

Java 源码:

java 复制代码
import java.util.Arrays;

public class RadixSortExample1 {
    public static void main(String[] args) {
        int[] arr = {170, 45, 75, 90, 802, 24, 2, 66};
        radixSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void radixSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }

        int max = Arrays.stream(arr).max().getAsInt();
        int significantDigits = (int) Math.log10(max) + 1;

        for (int i = 1; i <= significantDigits; i *= 10) {
            countingSortByDigit(arr, i);
        }
    }

    private static void countingSortByDigit(int[] arr, int digit) {
        int n = arr.length;
        int[] output = new int[n];
        int[] count = new int[10];

        // 计算频率数组
        for (int i = 0; i < n; i++) {
            int digitValue = (arr[i] / digit) % 10;
            count[digitValue]++;
        }

        // 累计频率
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 根据频率数组和当前位的值,放置到输出数组
        for (int i = n - 1; i >= 0; i--) {
            int digitValue = (arr[i] / digit) % 10;
            output[count[digitValue] - 1] = arr[i];
            count[digitValue]--;
        }

        // 将输出数组复制回原数组
        System.arraycopy(output, 0, arr, 0, n);
    }
}

题目 2:基数排序处理负数

描述 :

给定一个包含负数的整数数组 arr,使用基数排序算法对其进行排序。

要求:

  • 能够处理负数。
  • 保持排序的稳定性。

示例 :

输入:[-12, -3, 0, 5, -17, 50, 6, 2]

输出:[-17, -12, -3, 0, 2, 5, 6, 50]

Java 源码:

java 复制代码
import java.util.Arrays;

public class RadixSortExample2 {
    public static void main(String[] args) {
        int[] arr = {-12, -3, 0, 5, -17, 50, 6, 2};
        radixSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void radixSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }

        int max = Arrays.stream(arr).max().getAsInt();
        int min = Arrays.stream(arr).min().getAsInt();
        int significantDigits = (int) Math.log10(Math.abs(max) + 1) + 1;

        for (int i = 1; i <= significantDigits; i *= 10) {
            countingSortByDigit(arr, i, min);
        }
    }

    private static void countingSortByDigit(int[] arr, int digit, int min) {
        int n = arr.length;
        int[] output = new int[n];
        int[] count = new int[10];

        // 计算频率数组
        for (int i = 0; i < n; i++) {
            int digitValue = ((arr[i] - min) / digit) % 10;
            count[digitValue]++;
        }

        // 累计频率
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 根据频率数组和当前位的值,放置到输出数组
        for (int i = n - 1; i >= 0; i--) {
            int digitValue = ((arr[i] - min) / digit) % 10;
            output[count[digitValue] - 1] = arr[i];
            count[digitValue]--;
        }

        // 将输出数组复制回原数组
        System.arraycopy(output, 0, arr, 0, n);
    }
}

题目 3:基数排序字符串数组

描述 :

给定一个字符串数组 arr,其中每个字符串表示一个整数,使用基数排序算法对这些整数进行排序。

要求:

  • 字符串可能包含前导零。
  • 保持排序的稳定性。

示例 :

输入:["100", "3", "20", "10"]

输出:["3", "10", "100", "20"]

Java 源码:

java 复制代码
import java.util.Arrays;

public class RadixSortExample3 {
    public static void main(String[] args) {
        String[] arr = {"100", "3", "20", "10"};
        radixSort(arr);
        System.out.println("Sorted array: " + Arrays.toString(arr));
    }

    public static void radixSort(String[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }

        int maxLen = Arrays.stream(arr).map(String::length).max().getAsInt();

        for (int i = 1; i <= maxLen; i++) {
            countingSortByDigit(arr, i);
        }
    }

    private static void countingSortByDigit(String[] arr, int digit) {
        int[] count = new int[10];
        String[] output = new String[arr.length];

        // 计算频率数组
        for (String s : arr) {
            int digitValue = (s.charAt(digit - 1) - '0');
            count[digitValue]++;
        }

        // 累计频率
        for (int i = 1; i < 10; i++) {
            count[i] += count[i - 1];
        }

        // 根据频率数组和当前位的值,放置到输出数组
        for (int i = arr.length - 1; i >= 0; i--) {
            String s = arr[i];
            int digitValue = (s.charAt(digit - 1) - '0');
            output[count[digitValue] - 1] = s;
            count[digitValue]--;
        }

        // 将输出数组复制回原数组
        System.arraycopy(output, 0, arr, 0, arr.length);
    }
}

这些题目和代码示例可以帮助你更好地理解和掌握基数排序算法,以及如何在实际问题中应用这一算法。在面试中,你可能会遇到类似的问题,希望这些示例能够帮助你做好准备。

相关推荐
xcl09251 小时前
北京24小时自助健身房系统软件开发实战:从架构到部署全流程指南
java·spring boot·架构
一 乐3 小时前
动漫书销售商城|基于springboot + vue动漫书销售商城(源码+数据库+文档)
java·数据库·vue.js·spring boot·毕业设计
卓怡学长3 小时前
w214基于jsp知道特产网
java·intellij-idea
步行cgn3 小时前
Spring 注解使用详解
java·spring
一条小小yu3 小时前
Spring IoC的理解
java·后端·spring
落魄实习生4 小时前
Agent Scope Java 2.x 系列【7】工具使用
java·开发语言·ai
旺仔学长 哈哈4 小时前
springboot钓鱼爱好者交流平台APP设计与实现
java·spring boot·mysql·充电桩管理系统
自强的小白5 小时前
核心功能(Service接口)
java·mybatis
乌暮6 小时前
深入理解 Java 泛型:把「万能盒子」用对、用稳
java·开发语言·后端·学习