1.1 文档目的
本文档对M源代码进行完整说明,包含程序功能、数据结构、核心逻辑、代码注释、缺陷分析、运行现象、源码全量带注释版本,供开发调试、课程实验查阅使用。
1.2 开发环境
- 开发语言:Java 8+
- 依赖集合类:ArrayList、HashMap、List、Map
- 包路径:com
1.3 整体功能
本程序在求解一个集合的子集的过程中,需要首先对集合进行从小到大排序,然后通过递归迭代求出所有子集。
1.4 程序缺点
求子集的前期是需要先对数进行排序,然后才能算出每个子集中包含的数字。不能在不排序的情况下求出所有子集。感兴趣都可以自己研究下 。
2 数据结构设计
全局共享容器 Map<String, List<List<Integer>>> map,三个固定 Key 承担不同存储职责:
表格
| list | List<List<Integer>> | 原始数据源,仅存放 1 个一维数组,即输入数字集合[1,4,6,7,8] |
| lists | List<List<Integer>> | 全局结果集,存放所有生成完成的递增子序列 |
| prev | List<List<Integer>> | 缓存上一轮递归产出的子序列,用于本轮拼接生成更长子序列 |
辅助局部变量说明:
3 核心方法说明
3.1 递归方法 getR
方法签名
java
运行
public static Map<String, List<List<Integer>>> getR(Map<String, List<List<Integer>>> map)
入参
map:全局数据容器,包含原始数据、结果集、上一轮子序列缓存
返回值
传入的原Map对象(引用传递,内部数据已被递归修改)
分支逻辑拆分
分支 1:prev 为空(首次递归入口)
分支 2:prev 存在数据(扩展更长子序列)
4 Main 主方法执行流程
5 完整代码如下
java
运行
package com;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 递归生成严格递增子序列程序
* 功能:基于有序数字数组,递归构造全部严格递增子序列
* 缺陷:无递归终止条件,无限递归触发栈溢出StackOverflowError
*/
public class MyProject {
/**
* 递归核心函数,循环扩展生成递增子序列
* @param map 全局数据存储容器
* key=list:原始一维数字数组(二维包装)
* key=lists:所有递增子序列总结果集
* key=prev:上一轮生成的子序列缓存,用于拼接更长序列
* @return 修改完成数据后的map引用对象
*/
public static Map<String,List<List<Integer>>> getR( Map<String,List<List<Integer>>> map){
// 获取原始数字一维数组 [1,4,6,7,8]
List<Integer> list=map.get("list").get(0);
// 获取全局结果集合,存放所有子序列
List<List<Integer>> lists=map.get("lists");
// 定义变量接收上一轮子序列缓存
List<List<Integer>> listPrev=new ArrayList<>();
// 若prev缓存存在数据,则赋值给临时变量
if(map.get("prev").size()>0){
listPrev=map.get("prev");
}
// 判断:存在上一轮生成的子序列,需要拼接更长序列
if(listPrev!=null&&listPrev.size()>0){
// 空分支,无任何处理逻辑,冗余代码
if(listPrev.size()==1){
}else{
// u存储本轮新生成的加长子序列,作为下一轮prev缓存
List<List<Integer>> u=new ArrayList<>();
// 遍历上一轮所有短子序列
for(int i=0;i<listPrev.size();i++){
// 复制当前子序列,防止修改原缓存集合
List<Integer> l=new ArrayList<>();
l.addAll(listPrev.get(i));
// 遍历原始数组所有数字,尝试尾部追加
for(int j=0;j<list.size();j++){
// 严格递增判定:序列最后一位小于待追加数字
if(l.get(l.size()-1)<list.get(j)){
// 构建新子序列
List<Integer> list1=new ArrayList<>();
list1.addAll(l);
// 追加更大数值,生成长度+1的递增子序列
list1.add(list.get(j));
// 存入全局结果集
lists.add(list1);
// 存入本轮临时集合,用于下一轮递归
u.add(list1);
}
}
// 同步更新map内的结果集
map.put("lists", lists);
}
// 将本轮生成序列设置为下一轮的prev缓存
map.put("prev", u);
// 递归调用,继续生成更长子序列
getR(map);
}
}else{
// 首次递归:prev缓存为空,生成长度为1的单元素子序列
List<List<Integer>> u=new ArrayList<>();
// 遍历原始数组每一个数字
for(int i=0;i<list.size();i++){
List<Integer> l=new ArrayList<>();
l.add(list.get(i));
// 存入全局结果
lists.add(l);
// 存入临时集合,作为下一轮prev数据
u.add(l);
}
// 更新map缓存与结果集
map.put("prev", u);
map.put("lists",lists);
// 递归进入长序列扩展逻辑
getR(map);
}
// 返回数据容器
return map;
}
public static void main(String[] args) {
// 原始数字一维数组
List<Integer> l=new ArrayList<>();
// 全局数据存储Map
Map<String,List<List<Integer>>> map=new HashMap<>();
// 二维包装容器,用于存放原始一维数组
List<List<Integer>> m=new ArrayList<>();
// 初始化全局子序列结果集合
List<List<Integer>> n=new ArrayList<>();
// 初始化prev空缓存集合
List<List<Integer>> u=new ArrayList<>();
// 将空结果集、空前置缓存存入map
map.put("lists",n);
map.put("prev", u);
// 填充待处理有序数字
l.add(1);
l.add(4);
l.add(6);
l.add(7);
l.add(8);
// 一维数组包装进二维集合
m.add(l);
// 原始数据源存入map
map.put("list", m);
// 调用递归生成所有递增子序列(会无限递归栈溢出)
map=getR(map);
// 取出递归后的结果集合(代码无法执行到此处)
List<List<Integer>> lists1=map.get("lists");
// 创建空一维列表
List<Integer> l1=new ArrayList<Integer>();
// 将空列表插入结果集合首位
lists1.add(l1);
// 覆盖map内的结果集
map.put("lists", lists1);
// 控制台打印输出(代码无法执行到此处)
System.out.println(lists1);
}
}



