Java使用递归打印数组所有子序列 递归传入输入列表存在问题
问题说明
需要使用Java语言通过递归方式实现数组所有子序列的打印功能,现有代码运行后无法输出正确结果,已定位问题出在递归调用时传入的输入列表处理逻辑上,原问题代码如下:
import java.util.ArrayList; import java.util.Collections; public class abc { public static void m(ArrayList<Integer> op, ArrayList<Integer> ip) { if(ip.size()==0) { System.out.println(op); return; } ArrayList<Integer> l1=new ArrayList<Integer>(); ArrayList<Integer> l2=new ArrayList<Integer>(); l1.addAll(op); l2.addAll(op); l1.add(ip.get(0)); ip.remove(0); m(l2,ip); m(l1,ip); } public static void main(String[] args) { Integer [] z = {1,3,2}; ArrayList<Integer> ip=new ArrayList<Integer>(); Collections.addAll(ip, z); ArrayList<Integer> op=new ArrayList<Integer>(); m(op,ip); } }
错误原因
- 原代码直接对传入的共享
ip列表执行remove(0)修改操作,两个递归分支共用同一个被修改的列表对象。第一个递归分支执行过程中会持续修改ip的内容,等第二个递归分支开始执行时,ip里的待处理元素已经被之前的操作删空,导致大量子序列丢失。 - 递归的两个选择分支(选当前元素/不选当前元素)没有做到状态隔离,输入列表的修改互相干扰。
修复后代码
修复核心是给两个递归分支传入独立的输入列表副本,不直接修改原方法传入的ip对象:
import java.util.ArrayList; import java.util.Collections; public class abc { public static void m(ArrayList<Integer> op, ArrayList<Integer> ip) { if(ip.size()==0) { System.out.println(op); return; } Integer current = ip.get(0); // 构造去掉首元素的独立输入列表副本,供两个递归分支使用 ArrayList<Integer> nextIp = new ArrayList<>(ip.subList(1, ip.size())); ArrayList<Integer> opNotPick = new ArrayList<>(op); ArrayList<Integer> opPick = new ArrayList<>(op); opPick.add(current); // 不选当前元素的分支 m(opNotPick, nextIp); // 选当前元素的分支 m(opPick, nextIp); } public static void main(String[] args) { Integer [] z = {1,3,2}; ArrayList<Integer> ip=new ArrayList<Integer>(); Collections.addAll(ip, z); ArrayList<Integer> op=new ArrayList<Integer>(); m(op,ip); } }
运行结果
输入数组[1,3,2]时,修复后的代码会输出全部8个正确子序列:
[] [2] [3] [3, 2] [1] [1, 2] [1, 3] [1, 3, 2]
内容的提问来源于stack exchange,提问作者Sourabh Gayake
相关产品推荐
相关产品推荐

