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

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

相关推荐
Buleall2 分钟前
期末考学C
java·开发语言
重生之绝世牛码4 分钟前
Java设计模式 —— 【结构型模式】外观模式详解
java·大数据·开发语言·设计模式·设计原则·外观模式
小蜗牛慢慢爬行10 分钟前
有关异步场景的 10 大 Spring Boot 面试问题
java·开发语言·网络·spring boot·后端·spring·面试
新手小袁_J34 分钟前
JDK11下载安装和配置超详细过程
java·spring cloud·jdk·maven·mybatis·jdk11
呆呆小雅35 分钟前
C#关键字volatile
java·redis·c#
Monly2136 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
Ttang2338 分钟前
Tomcat原理(6)——tomcat完整实现
java·tomcat
钱多多_qdd1 小时前
spring cache源码解析(四)——从@EnableCaching开始来阅读源码
java·spring boot·spring
waicsdn_haha1 小时前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
Q_19284999061 小时前
基于Spring Boot的摄影器材租赁回收系统
java·spring boot·后端