1

私は数独解決プログラムに取り組んでおり、9x9 ボードの各正方形の 1 から 9 までの数字を保持する配列リストが必要です。これらの配列リストのそれぞれは、その正方形に入る可能性のある数字に対応します。数字がその正方形に入ることができない場合、その数字はリストから削除されます。

たとえば、正方形 (3,5) に対応する配列リストから番号 7 を削除したい場合など、作業中の現在の正方形の配列リストを取得できるようにしたい

arrayOfLists[3][5].remove(Integer.valueOf(7));

しかし、これを行う方法がわかりません。配列を作成しようとすると、配列リストの配列を宣言する行でこのエラーが発生します

ArrayList のジェネリック配列を作成できません

これが私のコードです:

    //create arraylist
    ArrayList<Integer> nums = new ArrayList<Integer>();

    //fill arraylist with numbers 1-9
    for (int i = 1; i < 10; i++) {
        nums.add(i);
    }

    //create 9x9 array of arraylists
    ArrayList<Integer>[][] array = new ArrayList<Integer>[9][9];

    //fill each element of array with arraylist of numbers 1-9
    for(int i = 0; i<9; i++){
        for(int j = 0; j<9; j++){
            array[i][j] = nums;
        }       
    }

}

これは間違っていますか、それとも配列リストの配列を作成することはできませんか? それが不可能な場合、どうすればよいですか?

4

5 に答える 5

1

リストのリストを見るたびに、警報ベルが鳴り始めます。実際にそのようなことが必要な状況はまれであり、これはその 1 つではありません。

固定された 9 つの正方形、列、および行で構成される固定ボードがあり、各位置には 1 ~ 9 の数字が含まれます。

これらの概念のすべてに配列を使用します。これは、サイズが固定されており、各要素に直接アクセスする必要があるためです。コレクションには利点がなく、妨げになります。ロジック (場合によってはセット) を使用して、数値が各ゾーンで 1 回だけ使用されるようにします。

于 2013-08-24T00:56:51.930 に答える
1

配列リストの代わりにビット フィールドを使用します。つまり、ビット 1 ~ 9 が数値の可能性を表す整数を使用します。単一の数値のテスト、追加、削除は O(1) であり、メモリ サイズは固定されています。操作を認識している独自のオブジェクトに整数をカプセル化します。

于 2013-08-24T13:25:02.063 に答える
0

2 次元の使用を完全に削除し、各正方形に 1 ~ 81 の一意の番号を付けることで、単一のリストを保持できます。したがって、3,5 セルを使用している場合、それはリストの 9*2+5 = 23 番目の項目であることを意味します。これにより、リスト操作が大幅に簡素化されます。(3,5) 種類の参照を指定して、単一のメソッドを使用して一意のセル インデックスを指定できます。

于 2013-08-24T12:47:24.297 に答える
0

いくつかのこと:

1) for ループでは、array[i][j] = nums; これにより、配列の各要素で同じオブジェクトが生成されます。配列の 1 つの要素で remove() を呼び出すと、他のすべての要素に影響します。要素ごとに個別のリスト オブジェクトを作成します。

2) インターフェイスへのプログラム。ArrayList ではなく、nums を List として宣言します。

3) リストの配列ではなく、リストのリストを使用します。

    List<List<List<Integer>>> list = new ArrayList<List<List<Integer>>>();
    for(int i = 0; i<9; i++){
        List<List<Integer>> row = new ArrayList<List<Integer>>();
        for(int j = 0; j<9; j++){
            List<Integer> nums = new ArrayList<Integer>();
            for (int k = 1; k < 10; k++) {
                nums.add(i);
            }
            row.add(nums);
        }
        list.add(row);
    }

    // You can still get an element by index
    int x = list.get(3).get(1).remove(6);

しかし、これはちょっと扱いにくいです。ボードを表すクラスを作成することを検討してください。そうすれば、少なくともこれをより抽象化する操作ができます。

于 2013-08-24T00:29:00.880 に答える
-1

OK、これは私にとってはうまくいくようで、まだ落とし穴を見ていないので、これを回答として投稿します。

private static class IntegerArrayList extends ArrayList<Integer> {
    IntegerArrayList () { super(); }
    IntegerArrayList (Collection<? extends Integer> c) { super(c); }
    IntegerArrayList (int initialCapacity) { super(initialCapacity); }
}

今、あなたは次のようなことを言うことができます

IntegerArrayList[][] array = new IntegerArrayList[9][9];

array[1][2] のような要素は、すべての ArrayList メソッドを継承します (正常にarray[1][2].remove(something)動作します)。他のクラスでしか使用しない場合は、他のクラスにネストできると考えてクラスを作成しましたprivate staticが、必要に応じて公開することもできます。また、3 つのコンストラクターすべてを からコピーしましたArrayList。不要なものを削除することはできますが、やむを得ない理由はありません。

new ArrayList<Integer>[9][9]型チェックを行わない配列を作成するため(「型消去」のため)、問題は禁止されていると思います。ArrayList<Integer>しかし、から継承する独自の非ジェネリック型を追加すると、型の安全性が回復すると思います。

しかし、私は一般的な専門家ではありません。私よりも知識のある人がこのソリューションの問題を発見しても驚かないでしょう。しかし、チェックされていないタイプのものなどに関するコンパイラの警告はなく、私にとってはうまくいくように見えました。

(追記: よく聞かれる問題に対する一般的な解決策として、これを投稿しています。しかし実際には、この特定の問題については、他のように ArrayList の代わりにブール値の固定サイズの配列を使用するか、速度が実際の問題である場合は、整数を少しいじるかもしれません.)

于 2013-08-24T00:59:31.823 に答える