Java获得一个数组的指定长度排列组合算法示例

下面详细讲解一下Java获得一个数组的指定长度排列组合算法示例的完整攻略。

算法说明

在程序设计中,经常会遇到需要从给定的元素集合中去选取一些元素,这些元素能组成的各种可能长度的排列和组合集合。这时候,排列和组合问题就变得特别重要。在Java中,提供了一些工具类帮助我们解决这些问题。

排列和组合的定义

排列问题中,给定n个元素,从中选取k个元素进行排列,若n个元素都用上,排列结果为n!,若没有全部用上,排列的结果就为n(n-1)(n-2)……(n-k+1)

组合问题中,给定n个元素,从中选取k个元素进行组合,而k个元素的顺序不再是关注点,因此总的组合结果数就是C(n,k) = n! / (k!(n-k)!).

代码实现

下面是Java实现获取一个数组的指定长度排列和组合的示例:

import java.util.ArrayList;
import java.util.Arrays;

public class CombinationPermutation {
    /**
     * 组合算法
     *
     * @param ori      原数据集合
     * @param isRepeat 是否可重复取数
     * @param result   存储结果集的集合
     * @param begin    取数的起始下标
     * @param arr      临时存储已取数的数组
     * @param count    要取的数的个数
     */
    private static void combinationAlgorithm(int[] ori, boolean isRepeat, ArrayList<ArrayList<Integer>> result, Integer begin, Integer[] arr, int count) {
        if (count == 0) {
            result.add(new ArrayList<>(Arrays.asList(arr)));
            return;
        }
        for (int i = begin; i < ori.length; i++) {
            if (!isRepeat && i > begin && ori[i] == ori[i - 1]) {
                continue;
            }
            arr[arr.length - count] = new Integer(ori[i]);
            combinationAlgorithm(ori, isRepeat, result, i + 1, arr, count - 1);
        }
    }

    /**
     * 输入原数组,指定长度,获取所有组合数
     *
     * @param ori 原数据数组
     * @param len 指定的长度
     * @return 所有组合数
     */
    public static ArrayList<ArrayList<Integer>> getCombination(int[] ori, int len) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        if (ori == null || ori.length == 0 || ori.length < len || len < 1) {
            return result;
        }
        boolean isRepeat = false;
        Integer[] arr = new Integer[len];
        Arrays.sort(ori);
        combinationAlgorithm(ori, isRepeat, result, 0, arr, len);
        return result;
    }

    /**
     * 排列算法
     *
     * @param ori      原数组
     * @param isRepeat 是否可重复取数
     * @param result   存储结果集的ArrayList
     * @param arr      临时存储已经取出的数的数组
     * @param used     用来标记数字在当前排列中是否已经出现
     */
    private static void permutationAlgorithm(int[] ori, boolean isRepeat, ArrayList<ArrayList<Integer>> result, Integer[] arr, boolean[] used) {
        if (arr.length == ori.length) {
            result.add(new ArrayList<>(Arrays.asList(arr)));
            return;
        }
        for (int i = 0; i < ori.length; i++) {
            if (!isRepeat && used[i]) {
                continue;
            }
            if (isRepeat || (!isRepeat && (i == 0 || ori[i] != ori[i - 1] || used[i - 1]))) {
                arr[arr.length - ori.length + i] = new Integer(ori[i]);
                boolean[] tmpUsed = new boolean[used.length];
                System.arraycopy(used, 0, tmpUsed, 0, used.length);
                if (!isRepeat) {
                    //当前排列已包含该数字,将used设置为true,表示在接下来的递归中不能再使用这个数字
                    tmpUsed[i] = true;
                }
                permutationAlgorithm(ori, isRepeat, result, arr, tmpUsed);
            }
        }
    }

    /**
     * 输入原数组,指定长度,获取所有排列数
     *
     * @param ori 原数据数组
     * @param len 指定长度
     * @return 所有排列数
     */
    public static ArrayList<ArrayList<Integer>> getPermutation(int[] ori, int len) {
        ArrayList<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
        if (ori == null || ori.length == 0 || ori.length < len || len < 1) {
            return result;
        }
        boolean isRepeat = false;
        Integer[] arr = new Integer[len];
        boolean[] used = new boolean[ori.length];
        Arrays.sort(ori);
        permutationAlgorithm(ori, isRepeat, result, arr, used);
        return result;
    }

    public static void main(String[] args) {
        int[] ori = {1, 2, 3, 3};
        ArrayList<ArrayList<Integer>> combinationResult = getCombination(ori, 2);
        ArrayList<ArrayList<Integer>> permutationResult = getPermutation(ori, 2);
        System.out.println("数组 " + Arrays.toString(ori) + " 中选取 2 个数字的所有组合:");
        System.out.println(combinationResult.toString());
        System.out.println("数组 " + Arrays.toString(ori) + " 中选取 2 个数字的所有排列:");
        System.out.println(permutationResult.toString());
    }
}

注释中已经详细解释了排列和组合算法的实现过程,以及以上代码的实现方式。上面的代码中,针对组合和排列分别对应了getCombination和getPermutation方法,其中

  • getCombination方法输入原数组和指定长度,返回一个ArrayList,包含了所有的组合结果
  • getPermutation方法输入原数组和指定长度,返回一个ArrayList,包含了所有的排列结果

在实现时,以上两个方法都是通过类似DFS的递归方式实现,通过记录已经使用的数字,避免产生重复结果。

示例说明

针对以上算法,下面通过两个示例来说明排列和组合的生成过程:

示例1:从数组[1,2,3,3] 中选取2个数字的所有组合

下面是执行结果:

数组 [1, 2, 3, 3] 中选取 2 个数字的所有组合:
[[1, 2], [1, 3], [1, 3], [2, 3], [2, 3], [3, 3]]

结果中可以看到,选择 2 个数字进行组合,共有6个答案,其包括:[1,2]、[1,3]、[1,3]、[2,3]、[2,3]、[3,3]。

示例2:从数组[1,2,3,3]中选取2个数字的所有排列

下面是执行结果:

数组 [1, 2, 3, 3] 中选取 2 个数字的所有排列:
[[1, 2], [1, 3], [1, 3], [2, 1], [2, 3], [2, 3], [3, 1], [3, 2], [3, 3], [3, 1], [3, 2], [3, 3]]

结果中可以看到,选择两个数字进行排列,共有12个答案,其包括:[1,2]、[1,3]、[1,3]、[2,1]、[2,3]、[2,3]、[3,1]、[3,2]、[3,3]、[3,1]、[3,2]、[3,3]。

至此,我们已经详细讲解了Java获得一个数组的指定长度排列组合算法的完整攻略,希望这里的示例和说明对你有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java获得一个数组的指定长度排列组合算法示例 - Python技术站

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

相关文章

  • Spring Boot简介与快速搭建详细步骤

    SpringBoot简介与快速搭建详细步骤 什么是SpringBoot? SpringBoot是一个开源的Java框架,可用于构建可扩展的、高度可配置、轻量级的基于Spring的应用程序。它使用“使用约定优于配置”思想,目的是让程序员能够快速地搭建Spring程序,同时也降低了对Spring的配置需求。 SpringBoot的特点 基于Spring框架和其他…

    Java 2023年5月15日
    00
  • java 通过cmd 调用命令启动tomcat的操作

    启动Tomcat服务器一般有两种方式: 通过启动脚本启动Tomcat服务器 通过命令行启动Tomcat服务器 下面我将详细介绍如何通过Java代码通过命令行启动Tomcat服务器,以及实现该操作所需要的各种准备工作。 准备工作 在进行下面的步骤之前,需要确保机器上已经安装Java,并且已经配置好了环境变量。此外,也需要下载和安装Tomcat服务器,确保Tom…

    Java 2023年5月19日
    00
  • Java获取时间年、月、日的方法

    下面是详细讲解 Java 获取时间年、月、日的方法的攻略。 获取当前时间 Java 中获取当前时间的方法有很多种,下面介绍两种比较常见的方法: 方法一:使用 Date 类 可以使用 Java 中的 Date 类来获取当前时间,代码如下: import java.util.Date; public class GetCurrentTimeDemo { publ…

    Java 2023年5月20日
    00
  • Mybatis与Ibatis的区别

    Mybatis与Ibatis的区别 什么是Ibatis? Ibatis(或称为Apache Ibatis)是一款基于JDBC的持久化框架,它提供了一种将Java对象映射到SQL语句的方式。Ibatis通过XML文件配置SQL语句,然后在运行时使用这些SQL语句与数据库进行交互。Ibatis提供了很强的灵活性和控制权,开发者可以编写任意复杂的SQL语句。 什么…

    Java 2023年5月20日
    00
  • Javascript与PHP验证用户输入URL地址是否正确

    当我们需要用户输入URL地址时,我们需要验证用户输入的URL地址格式是否正确,这时候可以借助JavaScript和PHP两种语言来实现。 JavaScript验证用户输入URL地址是否正确 JavaScript提供了正则表达式的支持,可以利用正则表达式对用户输入的URL地址进行验证。 示例1:以下是利用JavaScript验证URL地址的示例代码。 func…

    Java 2023年6月15日
    00
  • 浅谈java object对象在heap中的结构

    浅谈Java Object对象在Heap中的结构 介绍 Java内存分为栈内存和堆内存,栈内存用于存储局部变量和方法调用的信息,而堆内存用于存储动态分配的对象和数组。在堆内存中,Java对象存储在对象头和对象实例数据两部分中。 Java对象头结构 Java对象在内存中的结构包括对象头和对象实例数据两部分,对象头的大小在不同的JVM实现中有所不同,取决于虚拟机…

    Java 2023年5月26日
    00
  • Spring(二):Spring通过IOC来创建对象

    下面是关于“Spring(二):Spring通过IOC来创建对象”的完整攻略: 一、什么是IoC IoC(Inversion of Control),即“控制反转”,是一种设计模式和思想。其主要思想是:将对象的创建、依赖注入等操作由程序员手动实现转化为由容器自动创建和注入,而程序员只需要定义好需要的组件和依赖关系,Spring容器就会负责管理、创建和注入对象…

    Java 2023年5月26日
    00
  • Java SiteMesh新手学习教程代码案例

    Java SiteMesh是一款用于网站脚手架开发的框架,它提供了一些Web应用程序的通用解决方案,如请求处理、网页模板、依赖注入等。对于一名初学者来说,学习Java SiteMesh可能会有些吃力,因此,在此提供一份完整的攻略,帮助新手了解Java SiteMesh框架。 1. 环境搭建 在学习Java SiteMesh前,我们需要先搭建好环境。以下是环境…

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