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

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

相关推荐
文丑颜不良啊6 小时前
LeetCode201~225题目解析
java·leetcode
SL_staff8 小时前
4G设备掉线三层归因指南:SIM卡、模组、JVS-IOT网关配置精准锁定
java·物联网·产品
Wang's Blog8 小时前
Java 项目实战: 交友项目 - 黑名单:取消黑名单
java·windows·交友
杨杨杨大侠9 小时前
DeepSeek Harness:连 Agent Loop 都能替换的插件架构
java·人工智能·agent
SL_staff9 小时前
私有化低代码运维三重雷区:JVS开源栈中的Kafka/ES/RabbitMQ治理实践
java·低代码·全栈
yuniko-n9 小时前
【算法】约瑟夫环问题
java·算法
Interview Aid1129 小时前
Snowflake OA 面试真题:前缀和、BFS 与动态规划
面试·动态规划·宽度优先
郝亚军9 小时前
manifest 中 `sha256` 与 `signValue` 的作用
java·开发语言·数据结构
譕痕9 小时前
stripe 实例
java·开发语言·stripe·checksession
墨子夕10 小时前
设计模式——Java × Python 双语言精讲 · 23 个经典模式 + 现代演进(前言篇)
java·开发语言·设计模式