Java递归时报错:java.lang.StackOverflowError,求解

干饭人之路 2019-02-08 12:20:34
/**
* xxx 20181018
* 从整形ArrayList source中 抽取n个元素,所构成的组合为 ArrayList<ArrayList<Integer>> result
* @param ArrayList<Integer> source
* @param int n
* @return ArrayList<ArrayList<Integer>> result
*/

public static ArrayList<ArrayList<Integer>> CombinationT(ArrayList<Integer> source,int n)
{ System.out.println("CombinationT(source,n):source.size()="+source.size()+"; n="+n);
ArrayList<ArrayList<Integer>> result=new ArrayList<ArrayList<Integer>>();
if(n==1)
{
for(int i=0;i<source.size();i++)
{ Object t=source.get(i);
ArrayList a= new ArrayList();
a.add(t);
result.add(a);
}
}
else if(source.size()==n)
{
result.add(source);
}
else
{
ArrayList<Integer> psource=new ArrayList<Integer>();
//[source.size()-1];
for(int i=0;i<source.size()-1;i++)
{
psource.add(source.get(i));
}
//报错信息所提示的84行代码
result.addAll(CombinationT(psource,n));
ArrayList<ArrayList<Integer>> tmp=CombinationT(psource,n-1);
for(int i=0;i<tmp.size();i++)
{
ArrayList<Integer> rs=new ArrayList<Integer>();
for(int j=0;j<n-1;j++)
{
rs.add(tmp.get(i).get(j));
}
rs.add(source.get(source.size()-1));
result.add(rs);
}
}
return result;
}


上面这个java写的组合方法在多次递归调用CombinationT后出现:
Exception in thread "main" java.lang.StackOverflowError
at com.fh.xt.utils.Combination.CombinationT(Combination.java:84)
at com.fh.xt.utils.Combination.CombinationT(Combination.java:84)
at com.fh.xt.utils.Combination.CombinationT(Combination.java:84)
...
的栈溢出报错,如何修改才能避免栈溢出???
...全文
1270 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
wrong1111 2019-02-22
  • 打赏
  • 举报
回复
引用 5 楼 weixin_38368556 的回复:
栈益处异常错误原因,我们知道栈由入栈和出栈,内的内存到校是固定的,当使用的内存超过了限制就会造成益处 影响栈益处的原因 1,一个是递归调用的方法栈太深所导致 2,一个是每个方法所占用的占内存太大 对于递归方法的使用一定要注意退出条件,并且尽量控制调用深度,如果深度太深可以把递归转化为循环的方式实现 对与每个方法栈的内存可以调节jvm的参数Xss 的大小,尽量设置小一点,可以增加递归调用的深度。
棒!
it-partner 2019-02-19
  • 打赏
  • 举报
回复
栈益处异常错误原因,我们知道栈由入栈和出栈,内的内存到校是固定的,当使用的内存超过了限制就会造成益处 影响栈益处的原因 1,一个是递归调用的方法栈太深所导致 2,一个是每个方法所占用的占内存太大 对于递归方法的使用一定要注意退出条件,并且尽量控制调用深度,如果深度太深可以把递归转化为循环的方式实现 对与每个方法栈的内存可以调节jvm的参数Xss 的大小,尽量设置小一点,可以增加递归调用的深度。
快乐先生 2019-02-12
  • 打赏
  • 举报
回复
无线递归会造成溢出,另外可以加大java使用的内存。
qq_39936465 2019-02-11
  • 打赏
  • 举报
回复
可以先求数字组合,最后在数字组合中加入元素,没必要在递归中加入元素,造成内存被大量占用。
loveljy_19901114 2019-02-08
  • 打赏
  • 举报
回复
看着也没啥错误,楼主可以试一下n比较小的情况下的运行情况,另外,楼主也可以采用一楼的意见改一下看看
qybao 2019-02-08
  • 打赏
  • 举报
回复
你要尽量避免无必要的递归和及时清空一些临时内存
首先
else if(source.size()==n) 改成 <=n, 因为size小n的全组合肯定一个而且全部元素都用到,没必要走到else递归直到n==1

其次
result.addAll(CombinationT(psource,n)); 改成 if (psource.size() <= n) {result.add(psource);} else {result.addAll(CombinationT(psource,n));}
因为当psource的size<=n时,psource的全组合肯定只有一个而且全部元素用到,没必要递归

再次
ArrayList<Integer> rs=new ArrayList<Integer>(); 改成 ArrayList<Integer> rs = tmp.get(i); 没有必要new
以下可以去掉
for(int j=0;j<n-1;j++)
{
rs.add(tmp.get(i).get(j));
}
其实你这样new一个rs,再把tmp(i)的所有元素添加,就等同于ArrayList<Integer> rs = tmp.get(i);而且直接rs = tmp.get(i);还可以避免new,少消耗内存

最后及时清空一些内存空间
在for(int i=0;i<tmp.size();i++)循环以后,清空tmp和psource
tmp.clear();
if (psource.size() > n) {
psource.clear();
}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧