0

指定された要素の配列に対して可能なすべての組み合わせを計算する Jave クラスがあり、これを行うために再帰メソッドを使用します。正常に動作しますが、入力要素の数が増えると、メモリ不足の問題が見つかりました。私がやりたいのは、特定のサイズのチャンクで組み合わせを計算することです。私の問題は、特に呼び出しの深さが高い場合に、再帰メソッドの状態を保存して復元する方法がわからないことです。以下はコードです。どうもありがとう。

package uty;

import java.io.FileOutputStream;
import java.util.ArrayList;

public class ESCalcCombination {

    int iMax = 0;
    boolean bEnd = false;
    int iLenInp;
    ArrayList<Integer[]> resultList;

    public ESCalcCombination(int[] inElements, int inMaxElem, int inMaxElemLen) {
        if (inMaxElem > 0) {
            iMax = inMaxElem;
        } else {
            iMax = new Double(Math.pow(2d, new Integer(inElements.length).doubleValue())).intValue();
        }
        resultList = new ArrayList(iMax);
        iLenInp = inElements.length;
        for (int i = 1; i <= iLenInp; i++) {
            if (inMaxElemLen > 0) {
                if (i > inMaxElemLen) {
                    break;
                }
            }
            for (int j = 0; j < iLenInp; j++) {
                if ((iLenInp - j) < i) {
                    break;
                }
                addNextElement(inElements, j, i, null);
                if (bEnd) {
                    break;
                }
            }
            if (bEnd) {
                break;
            }
        }
    }

    private void addNextElement(int[] inElements, int inCurIndex, int inLimitLen, ArrayList<Integer> inCurrentCombination) {
        if (inCurrentCombination != null
                && (inCurrentCombination.size() + (iLenInp - inCurIndex)) < inLimitLen) {
            return;
        }
        ArrayList<Integer> alCombinationLoc = new ArrayList();
        if (inCurrentCombination != null) {
            alCombinationLoc.addAll(inCurrentCombination);
        }
        alCombinationLoc.add(inElements[inCurIndex]);
        if (alCombinationLoc.size() == inLimitLen) {
            Integer[] arComb = new Integer[alCombinationLoc.size()];
            arComb = alCombinationLoc.toArray(arComb);
            resultList.add(arComb);
            alCombinationLoc.clear();
            alCombinationLoc = null;
            if (resultList.size() == iMax) {
                bEnd = true;
            }
            return;
        }
        for (int i = ++inCurIndex; i < iLenInp; i++) {
            addNextElement(inElements, i, inLimitLen, alCombinationLoc);
            if (bEnd) {
                return;
            }
        }
    }

    public void close() {
        ESUty.closeAL(resultList);
    }

    public ArrayList<Integer[]> getCombinations() {
        return resultList;
    }

    public static void main(String[] args) {
        ESCalcCombination ESCaCo = new ESCalcCombination(new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, 0, 15);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream("c:\\test\\conbinations.txt");
            for (int i = 0; i < ESCaCo.getCombinations().size(); i++) {
                StringBuilder sb = new StringBuilder();
                for (int j = 0; j < ESCaCo.getCombinations().get(i).length; j++) {
                    sb.append(ESCaCo.getCombinations().get(i)[j]);
                }
                System.out.println("elemento " + i + " = " + sb.toString());
                fos.write((sb.toString() + System.getProperty("line.separator")).getBytes());

            }
        } catch (Exception ex) {
            System.out.println("errore " + ex);
        } finally {
            ESUty.closeFileOutputStream(fos);

        }

        System.exit(0);
    }
}
4

1 に答える 1

1

再帰では、データの一部がスタックにあり、スタックを簡単に保存することはできません。そのような機能が必要な場合は、代わりに while ループをStackまたはArrayDequeデータ構造と一緒に使用してすべてを書き直してください。これにより、問題なく状態を保存および復元できます。

于 2013-07-09T07:52:00.083 に答える