2016-11-12 5 views
0

私は、スドクがJavaで有効であるかどうかをチェックして、(http://leetcode.tgic.me/valid-sudoku/index.html)に遭遇したかどうか確認したいと思います。SudokuがJavaで有効かどうかをチェックする方法は?

私はそれが行と列を検証しますが、3x3のグリッドバリデータのために方法を理解:

34   for(x = 0; x < mx; x += 3){ 
35    for(y = 0; y < my; y += 3){ 
36     
37     HashSet<Character> block = new HashSet<Character>(); 
38     
39     for(int offset = 0; offset < 9; offset++){ 
40      int ox = offset % 3; 
41      int oy = offset/3; 
42      
43      char c = board[x + ox][y + oy]; 
44      if(c != '.'){ 
45       if(block.contains(c)) return false; 
46      
47       block.add(c); 
48      } 
49     } 
50    } 
51   } 

offsetで、どのようにそれは3x3のグリッド内のすべてのセルをチェックするために役立ちますか?私はそれを強制してx=0, y=0offset=0と最初offset=1を試してみましたが、offset=1board[0 + 1][0+(1/3)] = board[1][1/3]ので、int ox = 1%3 = 1;int oy = 1/3与え、セル[1/3]がそうで何を表現しないブルート?

答えて

1

もしnをmで割ったとき、どちらもint(リテラルまたは変数のいずれか)なので、結果もintなので1/3 - > 0 したがって、 オフセット== 0 => ox = 0、oy = 0 オフセット== 1 => ox = 1、oy = 0 オフセット== 2 => ox = 2、oy = 0 オフセット== 3 - > ox = 0、oy = 1 ... ループはきれいに3行3列

+0

がそれを手に入れたかもしれません!私が答えを受け入れる前に、もう少し質問をしてください。 'int ox = offset%3;'と 'int oy = offset/3;'は3x3グリッドをループするのにどのように役立っていますか?そしてなぜ他のものより 'HashSet'ですか? –

+0

また、「0.6」の場合は1に丸めますか?または依然として「0」であるか? –

+0

@KuNole 'System.out.println'を追加して、' board'から値を取得しているところに 'x + ox'と' y + oy'があるのを見てください。それからあなたは見ることができるはずです。 – ajb

0

あなたHashSetアプローチのかなりよさそうだが、少し調整が必要となります...

仮定がある:ときに最初のブロック重複が無く、すべてのブロックの同じ位置が重複していない場合でも、スドクは解決されます。

外部ループでは、最初のブロックの値だけをトラフする必要があります。

あなたは、独自の「チェックセット」との内部ループにより、全てのブロックが同じ位置に別の番号を持っていることを、「最初のブロックチェックセット」に現在の値を追加し、チェックする必要があります:

First iteration 
1## 2## 3## 
### ### ### 
### ### ### 

4## 5## 5## 
### ### ### 
### ### ### 

7## 8## 9## 
### ### ### 
### ### ### 
firstBlock: [1] 

second iteration 
#2# #3# #4# 
### ### ### 
### ### ### 

#5# #6# #7# 
### ### ### 
### ### ### 

#8# #9# #1# 
### ### ### 
### ### ### 
firstBlock: [1,2] 

大きなトリックは、xy座標のループを避けることです。

Javaは私が座標を決定するためにオブジェクトを使用することをお勧めオブジェクト指向プログラミング言語ですので。私たちは配列でそれらを保持することができます(ブックマークを設定、私は通常、代わりに "コレクション"と言う...)と単純なforechループでそれを繰り返す...

また、私たちはいくつかのオブジェクト私はうまくいけばの有用性を実証し

public class SudokuCheck { 
    enum SudokuPosition { 
     p11(0, 0), p12(0, 1), p13(0, 2), 
     p21(1, 0), p22(1, 1), p23(1, 2), 
     p31(2, 0), p32(2, 1), p33(2, 2); 

     private final int x; 
     private final int y; 
     SudokuPosition(int x, int y) { 
      this.x = x; 
      this.y = y; 
     } 
     public int getX() {return x;}  
     public int getY() {return y;} 
    } 

    boolean check(int[][] sudoku) { 
     Set<Integer> firstBlockUniqueNumbers = new HashSet<>(); 
     for (SudokuPosition inBlock : SudokuPosition.values()) { 
      firstBlockUniqueNumbers.add(sudoku[inBlock.x][inBlock.y]); 

      Set<Integer> samePosInOtherBlocksUniqueNumbers = new HashSet<>(); 
      for (SudokuPosition ofBlock : SudokuPosition.values()) { 
       int sameXinAll = inBlock.x + offset(ofBlock.x); 
       int sameYinAll = inBlock.y + offset(ofBlock.y); 
       samePosInOtherBlocksUniqueNumbers.add(sudoku[sameXinAll][sameYinAll]); 
      } 
      if (9 > samePosInOtherBlocksUniqueNumbers.size()) 
       // numbers where not unique at current block position 
       // through all the blocks 
       return false; 
     } 
     return 9 == firstBlockUniqueNumbers.size(); 
    } 

    private int offset(int xOrY) { 
     return xOrY * 3; 
    } 
} 

:そうあなたはロジックは次のようになります :私たちは、そう私はこのようなJavaのenumsを使用することをお勧め (...それぞれに9位であり9つのブロック)を事前に知りますJavaの列挙型と優れた識別子名の重要性位置要素の名前が何とかにつながる可能性があり、そのコンストラクタ値を繰り返して交換することができるforechが

  • をループするJava 8ストリームAPIを使用して

    • 私は、このアプローチは2通りの方法で改善することができると思います厄介な間違い。後者はname()を経由して提供されていますが、このデモのためにあるとして十分かもしれません定数名にいくつかの巧妙な計算によって置き換え...

  • 関連する問題