zoukankan      html  css  js  c++  java
  • LeetCode算法笔记-回溯法

    一.解数独

    编写一个程序,通过已填充的空格来解决数独问题。

    一个数独的解法需遵循如下规则:

    • 数字 1-9 在每一行只能出现一次。
    • 数字 1-9 在每一列只能出现一次。
    • 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。

    空白格用 '.' 表示。

    class Solution {
      // box size
      int n = 3;
      // row size
      int N = n * n;
    
      int [][] rows = new int[N][N + 1];//记录每行数字d是否存在
      int [][] columns = new int[N][N + 1];//记录每列数字d是否存在
      int [][] boxes = new int[N][N + 1];//记录每个box是否存在d
    
      char[][] board;
    
      boolean sudokuSolved = false;
    
      public boolean couldPlace(int d, int row, int col) {
        /*
        Check if one could place a number d in (row, col) cell
        */
        int idx = (row / n ) * n + col / n;
        return rows[row][d] + columns[col][d] + boxes[idx][d] == 0;
      }
    
      public void placeNumber(int d, int row, int col) {
        /*
        Place a number d in (row, col) cell
        */
        int idx = (row / n ) * n + col / n;
    
        rows[row][d]++;
        columns[col][d]++;
        boxes[idx][d]++;
        board[row][col] = (char)(d + '0');
      }
    
      public void removeNumber(int d, int row, int col) {
        /*
        Remove a number which didn't lead to a solution
        */
        int idx = (row / n ) * n + col / n;
        rows[row][d]--;
        columns[col][d]--;
        boxes[idx][d]--;
        board[row][col] = '.';
      }
    
      public void placeNextNumbers(int row, int col) {
        /*
        Call backtrack function in recursion
        to continue to place numbers
        till the moment we have a solution
        */
        // if we're in the last cell
        // that means we have the solution
        if ((col == N - 1) && (row == N - 1)) {
          sudokuSolved = true;
        }
        // if not yet
        else {
          // if we're in the end of the row
          // go to the next row
          if (col == N - 1) backtrack(row + 1, 0);
            // go to the next column
          else backtrack(row, col + 1);
        }
      }
    
      public void backtrack(int row, int col) {
        /*
        Backtracking
        */
        // if the cell is empty
        if (board[row][col] == '.') {
          // iterate over all numbers from 1 to 9
          for (int d = 1; d < 10; d++) {
            if (couldPlace(d, row, col)) {
              placeNumber(d, row, col);
              placeNextNumbers(row, col);
              // if sudoku is solved, there is no need to backtrack
              // since the single unique solution is promised
              if (!sudokuSolved) removeNumber(d, row, col);
            }
          }
        }
        else placeNextNumbers(row, col);
      }
    
      public void solveSudoku(char[][] board) {
        this.board = board;
    
        // init rows, columns and boxes
        for (int i = 0; i < N; i++) {
          for (int j = 0; j < N; j++) {
            char num = board[i][j];
            if (num != '.') {
              int d = Character.getNumericValue(num);
              placeNumber(d, i, j);
            }
          }
        }
        backtrack(0, 0);
      }
    }
  • 相关阅读:
    【Unity学习笔记】Unity网络游戏开发实战(一)---网络编程的开端:Echo程序
    【DX11学习笔记】GerstnerWave波浪模拟(基于GPU计算着色器的实现)
    【DX11学习笔记】粒子系统--爆炸特效
    【设计模式】(二)观察者模式是什么?
    【设计模式】(一)工厂模式是什么?
    【C++笔记】C++中常见智能指针auto_ptr、unique_ptr、shared_ptr和weak_ptr的用法
    【C++笔记】C++关联容器set和map的概述和操作
    【C++笔记】C++函数模版与类模版
    【C++笔记】C++中vector、stack、deque、list的简易实际使用方法
    python之赋值、浅拷贝、深拷贝
  • 原文地址:https://www.cnblogs.com/ifreewolf/p/12701382.html
Copyright © 2011-2022 走看看