0

0

Java中求解最大互不相交子列表集合的回溯算法实现

霞舞

霞舞

发布时间:2026-03-02 09:19:07

|

760人浏览过

|

来源于php中文网

原创

Java中求解最大互不相交子列表集合的回溯算法实现

本文介绍如何在多个整数列表中,找出所有可能的“互不相交子集组合”,并筛选出长度最大的组合集合——即每个组合内各子列表两两无交集,且整体组合数量最多。核心在于建模为子集枚举+交集判定+回溯剪枝。

本文介绍如何在多个整数列表中,找出所有可能的“互不相交子集组合”,并筛选出长度最大的组合集合——即每个组合内各子列表两两无交集,且整体组合数量最多。核心在于建模为子集枚举+交集判定+回溯剪枝。

要解决“从给定多个列表中选出尽可能多的互不相交(disjoint)子列表组成一个组合”的问题,本质是最大独立集(Maximum Independent Set)在集合包含图上的变体:将每个输入列表视为图中的一个节点,若两个列表存在公共元素(即交集非空),则在对应节点间连边;目标即寻找最大团补集——也就是最大两两无边连接的节点集合,即最大互不相交子集族。

由于输入规模通常较小(如示例仅6个列表),我们采用回溯 + 位掩码/DFS 枚举 + 交集快速判定的策略,兼顾正确性与可读性。

妙刷AI
妙刷AI

美团推出的一款新奇、好玩、荒诞的AI视觉体验工具

下载

✅ 核心步骤解析

  1. 交集判定优化:使用 HashSet 预存每个列表,调用 Collections.disjoint(setA, setB) 或手动遍历,时间复杂度 O(min(|A|,|B|));
  2. 回溯构造合法组合:从索引 0 开始,对每个列表,决策“选 or 不选”——仅当其与当前已选列表全部不相交时才可加入;
  3. 最大化组合长度:记录当前最长合法组合长度(即所含子列表个数),只保留所有达到该最大长度的完整组合;
  4. 避免重复结果:因题目不要求顺序,且组合本身是列表的集合,我们按原始索引升序递归,天然避免排列重复(如 [list1,list2] 与 [list2,list1] 视为同一组合,仅生成前者)。

? 完整可运行示例代码

import java.util.*;

public class DisjointListCombiner {

    private static List<List<List<Integer>>> allMaxSolutions = new ArrayList<>();
    private static int maxLength = 0;

    public static List<List<List<Integer>>> findMaxDisjointCombinations(List<List<Integer>> lists) {
        allMaxSolutions.clear();
        maxLength = 0;
        backtrack(lists, 0, new ArrayList<>(), new HashSet<>());
        return allMaxSolutions;
    }

    private static void backtrack(List<List<Integer>> lists, int startIdx,
                                  List<List<Integer>> current, Set<Integer> usedElements) {

        // 更新全局最大长度并收集解
        if (current.size() > maxLength) {
            maxLength = current.size();
            allMaxSolutions.clear();
            allMaxSolutions.add(new ArrayList<>(current));
        } else if (current.size() == maxLength && maxLength > 0) {
            allMaxSolutions.add(new ArrayList<>(current));
        }

        // 尝试从 startIdx 开始选择后续列表
        for (int i = startIdx; i < lists.size(); i++) {
            List<Integer> candidate = lists.get(i);
            Set<Integer> candidateSet = new HashSet<>(candidate);

            // 检查是否与已选元素冲突
            if (Collections.disjoint(usedElements, candidateSet)) {
                // 选择:加入当前列表及所有元素
                current.add(candidate);
                usedElements.addAll(candidateSet);

                backtrack(lists, i + 1, current, usedElements);

                // 回溯:撤销选择
                current.remove(current.size() - 1);
                usedElements.removeAll(candidateSet);
            }
        }
    }

    // 测试入口
    public static void main(String[] args) {
        List<Integer> list1 = Arrays.asList(1, 2);
        List<Integer> list2 = Arrays.asList(3, 4);
        List<Integer> list3 = Arrays.asList(5, 6, 7);
        List<Integer> list4 = Arrays.asList(2, 3);
        List<Integer> list5 = Arrays.asList(7);
        List<Integer> list6 = Arrays.asList(3);

        List<List<Integer>> input = Arrays.asList(list1, list2, list3, list4, list5, list6);
        List<List<List<Integer>>> result = findMaxDisjointCombinations(input);

        System.out.println("共找到 " + result.size() + " 个最大互不相交组合(长度均为 " + result.get(0).size() + "):");
        for (int i = 0; i < result.size(); i++) {
            System.out.println((i + 1) + ". " + result.get(i));
        }
    }
}

⚠️ 注意事项与优化建议

  • 时间复杂度:最坏为 O(2ⁿ × n × m),其中 n 是列表总数,m 是平均列表长度;适用于 n ≤ 20 的场景。若 n 更大,建议改用贪心近似(如按列表长度降序 + 贪心选取)或转换为图的最大独立集求解器(如 Bron–Kerbosch 算法);
  • 元素类型限制:本实现假设元素可哈希(如 Integer, String),若含自定义对象,请确保 equals() 和 hashCode() 正确实现;
  • 去重处理:若输入列表本身存在重复(如两个完全相同的 [1,2]),需预先去重或调整逻辑以支持多重选择(本题未要求,故默认各列表唯一);
  • 内存友好提示:对超大规模输出,可将 allMaxSolutions 替换为回调接口(Consumer>> onSolution),实现流式处理。

✅ 总结

该问题不是简单过滤,而是组合搜索问题。通过回溯枚举 + 实时交集校验 + 最优性剪枝,我们能系统性地找出所有“最大互不相交子列表组合”。代码结构清晰、易于扩展(例如添加权重、限制总元素数等约束),是典型集合组合优化问题的 Java 实践范例。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

910

2023.08.02

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

1728

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

549

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2338

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

43

2026.01.19

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

483

2023.08.14

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

28

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

23

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

27

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4万人学习

C# 教程
C# 教程

共94课时 | 10.5万人学习

Java 教程
Java 教程

共578课时 | 74.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号