算法系列--递归,回溯,剪枝的综合应用(3)(下)

简介: 算法系列--递归,回溯,剪枝的综合应用(3)(下)

算法系列--递归,回溯,剪枝的综合应用(3)(上)

https://developer.aliyun.com/article/1480885?spm=a2c6h.13148508.setting.14.5f4e4f0euaAisj

💕"对相爱的人来说,对方的心意,才是最好的房子。"💕

作者:Lvzi

文章主要内容:算法系列–递归,回溯,剪枝的综合应用(3)

大家好,今天为大家带来的是算法系列--递归,回溯,剪枝的综合应用(3),带来几个比较经典的问题N皇后解数独,这两道都是hard级别的题目,但是不要被吓到!请看我的分析

2.有效的数独

:本题只是一个引子,是为了给解数独这道题目做引入

链接:

https://leetcode.cn/problems/valid-sudoku/description/

分析:

本题需要判断已经填入数字的数独是否有效,判断条件和N皇后那道题目的剪枝策略很像,具体的判断条件如下:

  1. 当前数字所在位置的相同不能有相同的数字
  2. 当前数字所在位置的相同不能有相同的数字
  3. 当前数字所在位置所处的九宫格不能有相同的数字

行和列只需要使用两个二维的布尔类型的数组进行标记即可,但是九宫格这个判断条件如何标记呢?这里用到了一个比较巧妙的策略,将连续的三个位置看成一个数字,

代码:

class Solution {
    boolean[][] row, col;
    boolean[][][] grid;
    public boolean isValidSudoku(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';
                    if(col[j][num] == true || row[i][num] == true || grid[i / 3][j / 3][num] == true)
                        return false;
                    col[j][num] = row[i][num] = grid[i / 3][j / 3][num] = true;
                }
            }
        }
        return true;
    }
}

3.解数独

链接:

https://leetcode.cn/problems/sudoku-solver/description/

分析:

很容易分析出本题是一个递归问题,因为每一步做的事情都是相同的

  • 存入数字,判断是否符合条件

递归的策略也容易想出–以一个一个的空格进行枚举

1.设计代码

全局变量

  • row[][],col[][]分别用于标记行和列
  • grid[][][]:用于标记九宫格

dfs:

  • 函数头:只需要传递原始的棋盘即可,返回值设置为boolean
  • 函数体:关注每一个子问题具体干的事情,在当前空位置从数字1枚举到数字9,判断是否符合添加的条件,如果可以,就填入,并递归下一个空位置
  • 递归出口:全部填充完毕

2.剪枝

注意有可能上一步的策略会导致当前位置无法填入任何数字,也就是上一步的策略是否有效需要递归到后面的子问题才能知道,一旦某个子问题中发现无法填入任何数字,证明上一步的策略是失败的,没有必要继续递归下去,此时就发生了剪枝,对于每一次递归来说,都需要返回一个布尔类型的数据,用于记录策略成功与否

3.回溯

回溯的策略和N皇后很像,恢复原状即可

代码:

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);
    }
    private 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;// 所有的空位都被填充
    }
}

一定要重点理解代码中三个return的实际含义

(本题真的很有意思,你可以利用上述代码快速的完成一道大师级的数独题目哦~笔者已经试过一次,真的很爽!!!)


目录
相关文章
|
1天前
|
机器学习/深度学习 算法
应用规则学习算法识别有毒的蘑菇
应用规则学习算法识别有毒的蘑菇
|
3天前
|
算法 决策智能 索引
数据结构与算法 回溯
数据结构与算法 回溯
7 1
|
6天前
|
存储 机器学习/深度学习 算法
R语言贝叶斯Metropolis-Hastings采样 MCMC算法理解和应用可视化案例
R语言贝叶斯Metropolis-Hastings采样 MCMC算法理解和应用可视化案例
|
6天前
|
数据采集 机器学习/深度学习 算法
数据分享|WEKA关联规则挖掘Apriori算法在学生就业数据中的应用
数据分享|WEKA关联规则挖掘Apriori算法在学生就业数据中的应用
|
10天前
|
机器学习/深度学习 自然语言处理 算法
机器学习算法原理与应用:深入探索与实战
【5月更文挑战第2天】本文深入探讨机器学习算法原理,包括监督学习(如线性回归、SVM、神经网络)、非监督学习(聚类、PCA)和强化学习。通过案例展示了机器学习在图像识别(CNN)、自然语言处理(RNN/LSTM)和推荐系统(协同过滤)的应用。随着技术发展,机器学习正广泛影响各领域,但也带来隐私和算法偏见问题,需关注解决。
|
11天前
|
机器学习/深度学习 算法 C语言
【C言专栏】递归算法在 C 语言中的应用
【4月更文挑战第30天】本文介绍了递归算法在C语言中的应用,包括基本概念(通过调用自身解决子问题)、特点(调用自身、终止条件、栈空间)和实现步骤(定义递归函数、分解问题、设置终止条件、组合解)。文中通过阶乘计算和斐波那契数列两个案例展示了递归的使用,强调了递归可能导致的栈溢出问题及优化需求。学习递归有助于理解和应用“分而治之”策略。
|
12天前
|
机器学习/深度学习 数据可视化 算法
【Python机器学习专栏】t-SNE算法在数据可视化中的应用
【4月更文挑战第30天】t-SNE算法是用于高维数据可视化的非线性降维技术,通过最小化Kullback-Leibler散度在低维空间保持数据点间关系。其特点包括:高维到二维/三维映射、保留局部结构、无需预定义簇数量,但计算成本高。Python中可使用`scikit-learn`的`TSNE`类实现,结合`matplotlib`进行可视化。尽管计算昂贵,t-SNE在揭示复杂数据集结构上极具价值。
|
1天前
|
算法 数据安全/隐私保护 计算机视觉
基于二维CS-SCHT变换和LABS方法的水印嵌入和提取算法matlab仿真
该内容包括一个算法的运行展示和详细步骤,使用了MATLAB2022a。算法涉及水印嵌入和提取,利用LAB色彩空间可能用于隐藏水印。水印通过二维CS-SCHT变换、低频系数处理和特定解码策略来提取。代码段展示了水印置乱、图像处理(如噪声、旋转、剪切等攻击)以及水印的逆置乱和提取过程。最后,计算并保存了比特率,用于评估水印的稳健性。
|
2天前
|
存储 算法 数据可视化
基于harris角点和RANSAC算法的图像拼接matlab仿真
本文介绍了使用MATLAB2022a进行图像拼接的流程,涉及Harris角点检测和RANSAC算法。Harris角点检测寻找图像中局部曲率变化显著的点,RANSAC则用于排除噪声和异常点,找到最佳匹配。核心程序包括自定义的Harris角点计算函数,RANSAC参数设置,以及匹配点的可视化和仿射变换矩阵计算,最终生成全景图像。
|
2天前
|
算法 Serverless
m基于遗传优化的LDPC码NMS译码算法最优归一化参数计算和误码率matlab仿真
MATLAB 2022a仿真实现了遗传优化的归一化最小和(NMS)译码算法,应用于低密度奇偶校验(LDPC)码。结果显示了遗传优化的迭代过程和误码率对比。遗传算法通过选择、交叉和变异操作寻找最佳归一化因子,以提升NMS译码性能。核心程序包括迭代优化、目标函数计算及性能绘图。最终,展示了SNR与误码率的关系,并保存了关键数据。
12 1