(算法)解数独————<递归>

1. 题⽬链接:37.解数独 

2. 题⽬描述:

3. 解法:

算法思路: 为了存储每个位置的元素,我们需要定义⼀个⼆维数组。⾸先,我们记录所有已知的数据,然后遍历 所有需要处理的位置,并遍历数字1~9。对于每个位置,我们检查该数字是否可以存放在该位置,同 时检查⾏、列和九宫格是否唯⼀。

我们可以使⽤⼀个⼆维数组来记录每个数字在每⼀⾏中是否出现,⼀个⼆维数组来记录每个数字在每 ⼀列中是否出现。对于九宫格,我们可以以⾏和列除以3得到的商作为九宫格的坐标,并使⽤⼀个三 维数组来记录每个数字在每⼀个九宫格中是否出现。在检查是否存在冲突时,只需检查⾏、列和九宫 格⾥对应的数字是否已被标记。如果数字⾄少有⼀个位置(⾏、列、九宫格)被标记,则存在冲突, 因此不能在该位置放置当前数字。

• 特别地,在本题中,我们需要直接修改给出的数组,因此在找到⼀种可⾏的⽅法时,应该停⽌递 归,以防⽌正确的⽅法被覆盖。

初始化定义:

1. 定义⾏、列、九宫格标记数组以及找到可⾏⽅法的标记变量,将它们初始化为false。

2. 定义⼀个数组来存储每个需要处理的位置。

3. 将题⽬给出的所有元素的⾏、列以及九宫格坐标标记为true。

4. 将所有需要处理的位置存⼊数组。

递归函数设计:void dfs(vector>& board, int pos)

参数:pos(当前需要处理的坐标);

返回值:⽆;

函数作⽤:在当前坐标填⼊合适数字,查找数独答案。

递归流程如下:

1. 结束条件:已经处理完所有需要处理的元素。如果找到了可⾏的解决⽅案,则将标记变量更新为 true并返回。

2. 获取当前需要处理的元素的⾏列值。

3. 遍历数字1~9。如果当前数字可以填⼊当前位置,并且标记变量未被赋值为true,则将当前位置的 ⾏、列以及九宫格坐标标记为true,将当前数字赋值给board数组中的相应位置元素,然后对下⼀ 个位置进⾏递归。

4. 递归结束时,撤回标记。 

C++算法代码: 

class Solution
{
public:
    //行、列、组状态数组
    bool hang[9][10], lie[9][10], zu[3][3][10];
    bool dfs(vector<vector<char>>& board, int h, int l)
    {
        //填数
        for (int i = h; i < 9; i++)
        {
            for (int j = l; j < 9; j++)
            {
                if (board[i][j] == '.')
                {
                    for (int k = 1; k < 10; k++)
                    {
                        if (!hang[i][k] && !lie[j][k] && !zu[i/3][j/3][k])
                        {
                            hang[i][k] = true;
                            lie[j][k] = true;
                            zu[i/3][j/3][k] = true;
                            board[i][j] = k + '0';
                            //如果之后的递归找到合适的数,则返回ture
                            if(dfs(board, i, j)==true)
                            {
                                return true;
                            }
                            hang[i][k] = false;
                            lie[j][k] = false;
                            zu[i/3][j/3][k] = false;
                            board[i][j] = '.';
                        }
                    }
                    //没找到返回false,尝试下一个数
                    return false;
                }
            }
        }
        //所有空填完了返回true
        return true;
    }
    void solveSudoku(vector<vector<char>>& board)
    {
        //状态数组初始化
        for (int i = 0; i < 9; i++)
        {
            for (int j = 0; j < 9; j++)
            {
                hang[i][board[i][j] - '0'] = true;
                lie[j][board[i][j] - '0'] = true;
                zu[i / 3][j / 3][board[i][j] - '0'] = true;
            }
        }
        dfs(board, 0, 0);
    }
};

Java算法代码:

class Solution
{
	boolean[][] row, col;
	boolean[][][] grid;
	public void solveSudoku(char[][] board)
	{
		row = new boolean[9][10];
		col = new boolean[9][10];
		grid = new boolean[3][3][10];
		// 初始化 
		for (int i = 0; i < 9; i++)
			for (int j = 0; j < 9; j++)
				if (board[i][j] != '.')
				{
					int num = board[i][j] - '0';
					row[i][num] = col[j][num] = grid[i / 3][j / 3][num] = true;
				}

		dfs(board);
	}
	public boolean dfs(char[][] board)
	{
		for (int i = 0; i < 9; i++)
		{
			for (int j = 0; j < 9; j++)
			{
				if (board[i][j] == '.')
				{
					// 填数 
					for (int num = 1; num <= 9; num++)
					{
						// 剪枝 
						if (!row[i][num] && !col[j][num] && !grid[i / 3][j / 3][num])
						{
							board[i][j] = (char)('0' + num);
							row[i][num] = col[j][num] = grid[i / 3][j / 3]
								[num] = true;
							if (dfs(board) == true) return true; // 重点理解 
							// 恢复现场 
							board[i][j] = '.';
							row[i][num] = col[j][num] = grid[i / 3][j / 3]
								[num] = false;
						}
					}
					return false; // 重点理解 
				}
			}
		}
		return true; // 重点理解 
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

课堂随笔

感谢支持~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值