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日

相关文章

  • java实现十六进制字符unicode与中英文转换示例

    下面是Java实现十六进制字符unicode与中英文转换的完整攻略。 概念介绍 Unicode是计算机科学领域中的一项标准,它对世界上所有的文字进行了编码,包括中文、英文、数字、符号等。其中,每个字符都有唯一的一个Unicode码,用16进制数表示。 Java中,使用\u来表示Unicode编码,比如\u0061代表小写字母”a”。 中英文转换就是把中文转换…

    Java 2023年5月20日
    00
  • Struts2和Ajax数据交互示例详解

    下面我将详细讲解“Struts2和Ajax数据交互示例详解”的完整攻略,包含以下几个部分: 概述:介绍本文的主要内容和目标。 环境配置:介绍Struts2和Ajax数据交互的环境配置。 示例1:使用Struts2和Ajax实现表单提交,并异步显示提交结果。 示例2:使用Struts2和Ajax实现无刷新分页查询。 1. 概述 本文将介绍如何实现 Struts…

    Java 2023年5月20日
    00
  • 三道java新手入门面试题,通往自由的道路–锁+Volatile

    三道Java新手入门面试题攻略 一、什么是锁? 锁是一种同步机制,用于控制多个线程对共享资源的访问。当多个线程试图访问同一共享资源时,可能会导致数据不一致或者其他问题,而锁就可以保证同一时刻只有一个线程访问该共享资源,避免多线程并发访问发生问题。 Java提供了两种锁机制:synchronized关键字和Lock接口。 synchronized关键字 syn…

    Java 2023年5月19日
    00
  • Java日常练习题,每天进步一点点(64)

    这篇文章是作者分享的 Java 练习题中的第 64 题,通过解答这道题目可以提高 Java 编程的能力。下面我们按照标准的 markdown 格式文本进行讲解。 标题 Java日常练习题,每天进步一点点(64) 任务描述 这道练习题要求实现一个单例模式。具体要求如下: 单例类的构造方法私有化,不允许从外界创建对象; 提供静态方法获取该单例对象; 多线程环境下…

    Java 2023年5月20日
    00
  • mybatis如何使用Java8的日期LocalDate和LocalDateTime详解

    下面就是“mybatis如何使用Java8的日期LocalDate和LocalDateTime详解”: 介绍 在开发中,有时候需要将 Java 的日期类型存在数据库中,mybatis 也同样支持这样的操作。本篇文章将详细介绍如何使用 Java8 的日期类型 LocalDate 和 LocalDateTime。 mybatis 配置 在 mybatis 中,需…

    Java 2023年5月20日
    00
  • 下载远程maven仓库的jar 手动放到本地仓库详细操作

    下面是下载远程maven仓库的jar并手动放到本地仓库的完整攻略。 前提条件 必须具备maven环境,安装教程可参考官方文档:Apache Maven 官方文档 已知需要下载的远程maven仓库地址 下载远程jar包并手动放到本地仓库 打开终端或命令行工具 使用以下命令下载远程maven仓库的jar mvn dependency:get -Dartifact…

    Java 2023年5月20日
    00
  • JNDI,JTA和JMS简介

    JNDI、JTA和JMS是JavaEE中非常重要的三个技术。它们分别用于实现面向对象的命名和目录服务、事务管理和消息传递。 JNDI简介 Java Naming and Directory Interface(JNDI)是一个面向对象的Java API,用于访问命名和目录服务。它提供了一种机制,使得Java应用程序能够发现和访问各种类型的命名服务,如文件系统…

    Java 2023年5月20日
    00
  • 关于Java中如何实现文件的读写操作

    做Java开发时经常需要对文件进行读写操作,下面是Java中实现文件读写操作的完整攻略: 文件读操作 在Java中,我们可以使用FileInputStream或BufferedInputStream类来读取文件。对于二进制文件可以直接用FileInputStream,对于文本文件最好使用BufferedInputStream。 FileInputStream…

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