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

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

相关推荐
闭着眼睛学算法几秒前
【双机位A卷】华为OD笔试之【模拟】双机位A-新学校选址【Py/Java/C++/C/JS/Go六种语言】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
java·c语言·javascript·c++·python·算法·华为od
源码_V_saaskw34 分钟前
JAVA校园跑腿校园外卖源码校园外卖小程序校园代买帮忙外卖源码社区外卖源码小程序+公众号+h5
java·开发语言·微信小程序·小程序
源码哥_博纳软云40 分钟前
JAVA同城预约服务家政服务美容美发洗车保洁搬家维修家装系统源码小程序+公众号+h5
java·开发语言·微信小程序·小程序
红尘客栈21 小时前
Kubernetes 集群调度
java·linux·网络·容器·kubernetes
编程岁月1 小时前
java面试-0203-java集合并发修改异常、快速/安全失败原理、解决方法?
java·开发语言·面试
whltaoin1 小时前
AI 超级智能体全栈项目阶段五:RAG 四大流程详解、最佳实践与调优(基于 Spring AI 实现)
java·人工智能·spring·rag·springai
junnhwan1 小时前
【苍穹外卖笔记】Day05--Redis入门与店铺营业状态设置
java·数据库·redis·笔记·后端·苍穹外卖
摇滚侠2 小时前
Spring Boot 3零基础教程,Spring Boot 特性介绍,笔记02
java·spring boot·笔记
Excuse_lighttime2 小时前
只出现一次的数字(位运算算法)
java·数据结构·算法·leetcode·eclipse
渣哥2 小时前
你以为只是名字不同?Spring 三大注解的真正差别曝光
javascript·后端·面试