数独 - 如何检查行,列,子方块中的重复项?

时间:2016-12-23 05:54:33

标签: java

所以,我试图制作一个包含整数1-9的List,用于检查以下内容:

  • 如果每行包含重复项
  • 对于每个列,如果它包含重复项
  • 对于9x9网格内的每个3x3平方,如果它包含重复项

但是,我不确定如何去做。最初我的方法会检查1-9,但不是重复:

public boolean getFrontier(int value)
{
 int n = 1;
    while(n <= 9)
    {
        if(value == n)
            return true;

        else n++;
    }
    return false;
}

现在,我尝试使用列表,但它并没有真正起作用......

  public boolean getFrontier(int value)
{
    ArrayList<Integer> reserve = new ArrayList<>();
    ListIterator iter = reserve.listIterator();

    for(int i = 1; i < 10; i++)    
    {
        reserve.add(i);
    }

    while(iter.hasNext())
    {
        int n = (int) iter.next();

        if(value == n)
            iter.remove();
        else if(!iter.hasNext() && value != n)
            return false;


    }
    return true;
}

如果有人可以解释我应该如何修复我的代码或提供更好的方法来检查重复项,我真的很感激!

6 个答案:

答案 0 :(得分:2)

简单的方法[O(n ^ 2)]

对于每个索引,检查另一个索引是否具有相同的值

final = df1.merge(df2, on=['key1', 'key2'], how='left')

更好的方式[O(n)]

对于每个索引,请保存该号码。如果多次看到一个数字,则表示重复。

for (int i=0; i<list.size(); i++)
    for (int j=i+1; j<list.size(); j++)
        if (list.get(i) == list.get(j))
            // found duplicate

委托方式(让一些数据集执行)

boolean[] seen = {false, false, false, false, false, false, false, false, false, false} for (int i : list) { if (seen[i]) // found duplicate else { seen[i] = true; } } 是一个没有重复的集合。

Set

&#34;时髦&#34;方式(流)

因为steam API非常棒(仅限Java 8):

HashSet(list).size() == list.size()

答案 1 :(得分:0)

我更新了这个答案,因为现在我觉得我明白了你的想法:

  • 检查每行是否包含重复项
  • 检查每列是否包含重复项
  • 检查9x9网格内的每个3x3正方形(如果它包含重复项)

示例性SudokuGrid

public class SudokuGrid {

    private Integer[][] values;

    public SudokuGrid(int size) {
      if (Math.sqrt(size) % 1 != 0) {
        throw new RuntimeException("Invalid grid size");
      }
      values = new Integer[size][size];
    }

    public void setValue(int row, int col, Integer value) {
      values[col][row] = value;
    }

    public boolean isSolved() {
      int size = values.length;
      int squareSize = (int) Math.sqrt(size);

      for (int i = 0; i < size; i++) {
        Integer[] row = new Integer[size];
        Integer[] square = new Integer[size];
        Integer[] column = values[i].clone();

        for (int j = 0; j < size; j++) {
          row[j] = values[j][i];
          square[j] = values
                          [(i / squareSize) * squareSize + j / squareSize]
                          [i * squareSize % size + j % squareSize];
        }

        if (!(validate(column) && validate(row) && validate(square))) {
          return false;
        }
      }

      return true;
    }

    private boolean validate(Integer[] check) {
      if (Arrays.asList(check).contains(null)) {
        return false;
      }

      int i = 0;
      Arrays.sort(check);
      for (int number : check) {
        if (number != ++i) { return false; }
      }
      return true;
    }
  }

用法:

SudokuGrid sudokuGrid = new SudokuGrid(9);
Integer[][] values = {{8, 2, 5, 4, 7, 1, 3, 9, 6},
                      {1, 9, 4, 3, 2, 6, 5, 7, 8},
                      {3, 7, 6, 9, 8, 5, 2, 4, 1},
                      {5, 1, 9, 7, 4, 3, 8, 6, 2},
                      {6, 3, 2, 5, 9, 8, 4, 1, 7},
                      {4, 8, 7, 6, 1, 2, 9, 3, 5},
                      {2, 6, 3, 1, 5, 9, 7, 8, 4},
                      {9, 4, 8, 2, 6, 7, 1, 5, 3},
                      {7, 5, 1, 8, 3, 4, 6, 2, 9}};

for(int i = 0; i < values.length; i++) {
  for(int j = 0; j < values.length; j++) {
    sudokuGrid.setValue(i, j, values[i][j]);
  }
}

System.out.println(sudokuGrid.isSolved());

打印:true

重要:

Credits&amp;解释here
我刚刚将代码修改为具有动态网格大小的完整类。

答案 2 :(得分:0)

如何在List中包含(Object o)方法?如果此列表包含指定的元素,它将返回true。

答案 3 :(得分:0)

java.util.Map将为您做正确的事。键将是从1到9的数字和值,例如它看到的次数。

或者,如果您只需要true/false类型的答案,则可以使用java.util.Set以及在其上调用add方法的时间,它会返回一个布尔值:如果设置尚未设置,则返回true包含指定的元素。

为了您的目的,这两个解决方案中的任何一个都比使用列表更清洁,更快。

答案 4 :(得分:0)

我没有完全得到问题,但是为了取出重复项,你可以使用HashSet。

class Test {
    HashSet hs = new HashSet();
    hs.add(1);
    hs.add(2);
    hs.add(1);
    System.out.println(hs);
}

输出就像 [1,2]

答案 5 :(得分:0)

@JAVANOOB据我了解你的要求,试试这个

public class Sudoku {

Integer values[] = new Integer[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
List<Integer> list = new ArrayList<Integer>(Arrays.asList(values));

public boolean getFrontier(int value) {
    if (list.contains(value)) {
        list.remove(list.indexOf(value));
        return true;
    }
    return false;
}

public static void main(String[] args) {
    Sudoku su = new Sudoku();
    System.out.println(su.getFrontier(2));
    System.out.println(su.getFrontier(2));

    System.out.println(su.getFrontier(3));
    System.out.println(su.getFrontier(3));

    System.out.println(su.getFrontier(2));
} }

首先返回true,然后返回false。

我希望有一个单独的逻辑来处理1 - 9之间的值。