Writing Is_Row_Ok()

The method Is_Row_Ok() takes the index of a row, and returns a boolean to say whether the row is valid for a Sudoku puzzle. To be valid, each entry of the row should be either a dash or a number, and no number should be repeated. The Read() method error checks the dash or number part. So all that Is_Row_Ok() needs to do is check for duplicate entries.

I take a minute in class and ask you to write it. Here's my solution:

bool Sudoku::Is_Row_Ok(int r) const
{
  vector <int> checker;     /* Use this to make sure no digit is set twice. */
  int c;

  checker.clear();
  checker.resize(10, 0);
  for (c = 0; c < 9; c++) {
    if (puzzle[r][c] != '-') {
      if (checker[puzzle[r][c]-'0']) return 0;
      checker[puzzle[r][c]-'0'] = 1;
    }
  }
  return 1;
}

The solution uses a 10-element vector to keep track of whether we've seen a number before. The running time complexity of this is simple -- O(n) where n is the number of elements in the row. That's as well as you can do.

Let's look at some worse solutions:

bool Sudoku::Is_Row_Ok(int r) const
{
  int i, j;

  for (i = 0; i < puzzle[r].size(); i++) {
    if (puzzle[r][i] != '-') {
      for (j = i+1; j < puzzle[r].size(); j++) {
        if (puzzle[r][i] == puzzle[r][j]) return false;
      }
    }
  }
  return true;
}

This is O(n2) because in the first iteration, the j loop can go n-1 elements. The next iteration is n-2 and so on. That's O(n2).

Here's another one:

bool Sudoku::Is_Row_Ok(int r) const
{
  char i;

  for (i = '1'; i <= '9'; i++) {
    if (puzzle[i].find(i) != puzzle[i].find_last_of(i)) return false;
  }
  return true;
}

While this is clever, it's also O(n2) because find() and find_last_of() both can run through the entire string.

And a last one:

vector <string> puzzle;

bool Is_Row_Ok(int r)
{
  char i;

  for (i = '1'; i <= '9'; i++) {
    if (puzzle[r].count(i) > 1) return false;
  }
  return true;
}

Well, first, there's no count() method of strings. And second, even if there were, it would be O(n2) again, because it would go through the entire string for each character.