如何用Java实现排列组合算法

下面是关于如何用Java实现排列组合算法的完整攻略:

排列组合算法实现

什么是排列与组合

排列是指选出m个元素,一次排成一个列,有序的称为$m$的排列,记为$A_m^n$

组合是指选出m个元素,无序的称为${m}$的组合,记作$C_m^n$

可以发现,排列与组合的关联非常大,在代码实现中,它们也是联系在一起的。

排列算法实现

递归算法

通过递归实现简单,下面为排列递归实现代码:

public static void permutation(char[] arr, int start, int end) {
    if (start == end) { 
        System.out.println(Arrays.toString(arr));
    } else {
        for (int i = start; i <= end; i++) {
            swap(arr, start, i);
            permutation(arr, start + 1, end);
            swap(arr, start, i);
        }
    }
}

public static void swap(char[] arr, int i, int j) {
    char temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}

该算法的时间复杂度为$O(n!)$,极其耗时。

非递归算法

非递归算法采用字典序法,可以将排列算法的时间复杂度降低到$O(n^2)$。

核心代码如下:

public static void nonRecPermutation(char[] arr) {
    Arrays.sort(arr);
    System.out.println(Arrays.toString(arr));
    while (true) {
        int i, j;
        // 找到逆序区域的头部(在末尾找到第一个升序的元素)
        for (i = arr.length - 2; i >= 0; i--) {
            if (arr[i] < arr[i + 1]) {
                break;
            }
            if (i == 0) {
                return;
            }
        }
        // 找到头部后面的最小升序元素
        for (j = arr.length - 1; j > i; j--) {
            if (arr[j] > arr[i]) {
                break;
            }
        }
        // 交换头尾元素
        swap(arr, i, j);
        // 翻转逆序区域
        reverse(arr, i + 1, arr.length - 1);
        System.out.println(Arrays.toString(arr));
    }
}

public static void reverse(char[] arr, int start, int end) {
    while (start < end) {
        swap(arr, start, end);
        start++;
        end--;
    }
}

组合算法实现

组合算法首先有一个求$C_n^m$的公式:

$$C_n^m=\frac{n!}{(n-m)!m!}$$

其实我们不必求出所有的组合,只需要找到第$k$个组合就行了,可以使用递归实现。

组合的递归实现代码如下:

public static void combination(char[] arr, int m, int start, char[] result, int index) {
    if (index == result.length) {
        System.out.println(Arrays.toString(result));
    } else {
        for (int i = start; i <= arr.length - m + index; i++) {
            result[index] = arr[i];
            combination(arr, m, i + 1, result, index + 1);
        }
    }
}

该算法的时间复杂度为$O(C_n^m)$。

示例

下面为排列和组合的示例代码:

public static void main(String[] args) {
    char[] arr = {'a', 'b', 'c'};
    // 排列
    permutation(arr, 0, arr.length - 1);
    nonRecPermutation(arr);
    // 组合
    char[] result = new char[2];
    combination(arr, 2, 0, result, 0);
}

以上就是用Java实现排列组合算法的方法,包括排列的递归和非递归实现以及组合的递归实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:如何用Java实现排列组合算法 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 详解通过JDBC进行简单的增删改查(以MySQL为例)

    以下是详解通过JDBC进行简单的增删改查的攻略: JDBC简介 Java Database Connectivity(JDBC)是Java语言中访问数据库的一种标准方式,它提供了一种访问不同数据库的标准方法。通过JDBC,开发者可以使用Java程序连接到不同的数据库,执行SQL查询,以及处理查询结果。 JDBC使用流程 通常,使用JDBC完成数据库操作,流程…

    Java 2023年5月20日
    00
  • 剑指Offer之Java算法习题精讲链表专题篇

    这篇文章主要是讲解《剑指Offer》中链表专题的相关算法习题的解法,并使用Java语言实现。其中包括链表的基本操作、链表的快慢指针应用、链表的反转、链表的合并等。接下来,我将从以下几个方面逐一介绍该篇文章的内容。 标题 文章的每一部分都应该用适当的标题进行标识,方便读者阅读和理解。 代码块 在介绍算法的过程中,应该包含合适的代码块,以便读者更加清晰地理解算法…

    Java 2023年5月19日
    00
  • springboot+gradle 构建多模块项目的步骤

    下面是详细讲解“springboot+gradle 构建多模块项目的步骤”的完整攻略。 四步构建多模块项目 第一步:创建父项目 在开始构建多模块项目之前,我们需要先创建一个父项目,用于管理多个子模块的依赖关系。使用gradle构建的项目通常有一个根目录,这个根目录下通常会有一个build.gradle文件,当然也可以包含其他文件和目录,具体的结构可以按照实际…

    Java 2023年5月31日
    00
  • Java如何在命令行中获取指定数据

    以下是关于Java在命令行中获取指定数据的攻略: 1.概述 在Java中,我们可以通过命令行参数获取指定的数据。命令行参数是一种程序传递信息给它自身的传统方式,当您调用一个Java程序时,它可以通过命令行中的参数来获取一些额外的信息。这样,程序就可以根据这些参数来执行不同的逻辑或操作。 2.获取命令行参数 在Java中,获取命令行参数是非常简单的。当您运行一…

    Java 2023年5月26日
    00
  • MyBatis传入数组集合类并使用foreach遍历

    MyBatis是一款流行的Java ORM框架,可以用于简化数据库操作。这里将详细讲解如何在MyBatis中传入数组集合类并使用foreach进行遍历。 第一步:传入数组集合类 在MyBatis中,可以通过使用@Param注解来传递参数。@Param注解需要指定参数的名称,例如: <select id="selectUsersByIds&qu…

    Java 2023年5月26日
    00
  • Java多线程的用法详解

    Java多线程的用法详解 Java多线程是Java编程中非常重要的一个部分,在Java中通过多线程实现并发编程,提高程序的执行效率与响应能力,本文将详细讲解Java多线程的用法。 为什么需要多线程? 在介绍Java多线程之前,我们需要了解为什么需要多线程。首先,操作系统分给每个进程固定的资源是有限的,而非多线程的单进程只能利用其中一个CPU并执行一个任务。而…

    Java 2023年5月19日
    00
  • SpringBoot 的 web 类型推断详解

    Spring Boot是一个快速开发框架,可以帮助开发人员快速构建Web应用程序。在开发过程中,经常需要处理HTTP请求和响应。为了简化开发,Spring Boot提供了Web类型推断功能,可以自动推断HTTP请求和响应的类型。本文将介绍Spring Boot的Web类型推断功能,并提供两个示例。 什么是Web类型推断? Web类型推断是Spring Boo…

    Java 2023年5月15日
    00
  • Java中的拦截器、过滤器、监听器用法详解

    Java中的拦截器、过滤器、监听器用法详解 Java中的拦截器、过滤器、监听器是Web开发中常用的几种组件,它们可以用于拦截、修改请求和响应、监听特定事件等。本文将详细讲解它们的用法。 过滤器(Filter) 在Java Web应用中,过滤器可以用于拦截请求和响应,这使得过滤器非常有用,能够实现很多功能,例如:HTTP缓存、字符编码、安全等。 以下是一个过滤…

    Java 2023年6月15日
    00
合作推广
合作推广
分享本页
返回顶部