练习题(2024/5/22)

news2024/12/23 17:00:27

1N 皇后 II

n 皇后问题 研究的是如何将 n 个皇后放置在 n × n 的棋盘上,并且使皇后彼此之间不能相互攻击。

给你一个整数 n ,返回 n 皇后问题 不同的解决方案的数量。

示例 1:

输入:n = 4
输出:2
解释:如上图所示,4 皇后问题存在两个不同的解法。

示例 2:

输入:n = 1
输出:1

提示:

  • 1 <= n <= 9

思路:

  1. 回溯算法:

    • 使用回溯算法探索所有可能的解空间。从棋盘的第一行开始,逐行尝试在每一列放置皇后,并检查是否满足 N 皇后问题的要求。
    • 如果当前位置可以放置皇后,则递归到下一行,继续尝试放置下一个皇后。
    • 如果某一行无法放置皇后,或者已经放置了 N 个皇后,尝试改变之前的放置,进行回溯。
  2. isValid 函数:

    • isValid 函数用于检查在给定位置放置皇后是否合法,即是否满足 N 皇后问题的要求。
    • 检查条件包括:列上是否有皇后、左上方是否有皇后、右上方是否有皇后。
  3. 总结解的数量:

    • 使用一个私有变量 count 记录符合条件的解的数量。
    • 每当成功放置 N 个皇后,即遍历完所有行后,增加 count 的值。
  4. totalNQueens 函数:

    • totalNQueens 函数作为入口点,初始化一个大小为 N x N 的棋盘,并调用 backtracking 函数开始搜索解空间。
    • 最终返回符合条件的解的数量。

代码:

class Solution {
private:
int count = 0;
void backtracking(int n, int row, vector<string>& chessboard) {
    if (row == n) { // 如果已经遍历完所有行,表示找到了一个解
        count++;
        return;
    }
    for (int col = 0; col < n; col++) {
        if (isValid(row, col, chessboard, n)) {
            chessboard[row][col] = 'Q'; // 放置皇后
            backtracking(n, row + 1, chessboard); // 继续下一行的放置
            chessboard[row][col] = '.'; // 回溯,尝试其他位置
        }
    }
}
bool isValid(int row, int col, vector<string>& chessboard, int n) {
    // 检查列
    for (int i = 0; i < row; i++) { // 检查列是否有皇后
        if (chessboard[i][col] == 'Q') {
            return false;
        }
    }
    // 检查 45度角是否有皇后
    for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) {
        if (chessboard[i][j] == 'Q') { // 检查左上方是否有皇后
            return false;
        }
    }
    // 检查 135度角是否有皇后
    for(int i = row - 1, j = col + 1; i >= 0 && j < n; i--, j++) {
        if (chessboard[i][j] == 'Q') { // 检查右上方是否有皇后
            return false;
        }
    }
    return true; // 该位置可以放置皇后
}

public:
    int totalNQueens(int n) {
        std::vector<std::string> chessboard(n, std::string(n, '.')); // 初始化棋盘
        backtracking(n, 0, chessboard); // 回溯搜索解空间
        return count; // 返回解的个数
    }
};

2分割回文串 II

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是

回文串

返回符合要求的 最少分割次数 。

示例 1:

输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

示例 2:

输入:s = "a"
输出:0

示例 3:

输入:s = "ab"
输出:1

提示:

  • 1 <= s.length <= 2000
  • s 仅由小写英文字母组成

思路:

  1. 构建一个二维数组 isPalindromic,用来记录字符串 s 中每个子串是否为回文串。
  2. 遍历字符串 s,填充 isPalindromic 数组,判断每个子串是否为回文串。
  3. 初始化一个一维数组 dp,用来记录从第一个字符到当前位置字符所需的最小切割次数,初始值为每个位置的索引值。
  4. 动态规划计算最小切割次数:
    • 如果当前位置到第一个位置的子串本身就是回文串,则该位置的最小切割次数为 0。
    • 否则,在前面的子串中找到最小切割次数,并更新当前位置所需的最小切割次数。
  5. 返回 dp 数组中最后一个位置的值,即从第一个字符到最后一个字符的最小切割次数

代码:

class Solution {
public:
    int minCut(string s) {
        // 初始化一个二维数组,用来存储从位置 i 到 j 的子串是否是回文串
        vector<vector<bool>> isPalindromic(s.size(), vector<bool>(s.size(), false));
        
        // 填充 isPalindromic 数组
        for (int i = s.size() - 1; i >= 0; i--) {
            for (int j = i; j < s.size(); j++) {
                // 判断 s[i] 到 s[j] 是否是回文串
                if (s[i] == s[j] && (j - i <= 1 || isPalindromic[i + 1][j - 1])) {
                    isPalindromic[i][j] = true;
                }
            }
        }
        
        // 初始化一个一维数组 dp,用来记录从第一个字符到第 i 个字符需要的最小切割次数
        vector<int> dp(s.size(), 0);
        for (int i = 0; i < s.size(); i++) {
            dp[i] = i; // 初始值设为 i
        }

        // 动态规划计算最小切割次数
        for (int i = 1; i < s.size(); i++) {
            // 如果从第一个字符到第 i 个字符是回文串,最小切割次数为 0
            if (isPalindromic[0][i]) {
                dp[i] = 0;
                continue;
            }
            // 在不是回文串的情况下,循环遍历前面的子串找到最小切割次数
            for (int j = 0; j < i; j++) {
                if (isPalindromic[j + 1][i]) {
                    // 更新最小切割次数为当前位置与前一个回文串位置的切割次数加 1
                    dp[i] = min(dp[i], dp[j] + 1);
                }
            }
        }
        return dp[s.size() - 1]; // 返回从第一个字符到最后一个字符的最小切割次数
    }
};

3最长递增子序列的个数

给定一个未排序的整数数组 nums , 返回最长递增子序列的个数 。

注意 这个数列必须是 严格 递增的。

示例 1:

输入: [1,3,5,4,7]
输出: 2
解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]。

示例 2:

输入: [2,2,2,2,2]
输出: 5
解释: 最长递增子序列的长度是1,并且存在5个子序列的长度为1,因此输出5。

提示: 

  • 1 <= nums.length <= 2000
  • -106 <= nums[i] <= 106

思路:

  1. 定义状态: 定义两个数组 dp 和 count,其中 dp[i] 表示以第 i 个元素结尾的最长递增子序列的长度,count[i] 表示以第 i 个元素结尾的最长递增子序列的个数。

  2. 状态转移方程: 对于每个元素 nums[i],遍历其之前的元素 nums[j](其中 j < i),如果 nums[i] > nums[j],则:

    • 如果 dp[j] + 1 > dp[i],则更新 dp[i] = dp[j] + 1,并且 count[i] 更新为之前的 count[j]
    • 如果 dp[j] + 1 == dp[i],则累加 count[i] += count[j]
  3. 计算最终结果: 找到最长递增子序列的长度 maxCount,然后遍历 dp 数组,将所有长度为 maxCount 的递增子序列的个数相加,得到最终的结果。

代码:

class Solution {
public:
    int findNumberOfLIS(vector<int>& nums) {
        // 如果数组长度小于等于1,直接返回数组长度
        if (nums.size() <= 1) return nums.size();
        
        // 初始化动态规划数组 dp 和计数数组 count
        vector<int> dp(nums.size(), 1); // dp[i] 表示以第 i 个元素结尾的最长递增子序列的长度
        vector<int> count(nums.size(), 1); // count[i] 表示以第 i 个元素结尾的最长递增子序列的个数
        
        int maxCount = 0; // 用于记录最长递增子序列的长度
        
        // 遍历数组进行动态规划
        for (int i = 1; i < nums.size(); i++) {
            for (int j = 0; j < i; j++) {
                if (nums[i] > nums[j]) {
                    // 更新 dp 和 count
                    if (dp[j] + 1 > dp[i]) { // 如果能取得更长的递增子序列
                        dp[i] = dp[j] + 1;
                        count[i] = count[j]; // 更新计数为之前的 count[j]
                    } else if (dp[j] + 1 == dp[i]) {
                        // 如果有相同长度的递增子序列出现,累加计数
                        count[i] += count[j];
                    }
                }
                
                // 更新最长递增子序列的长度
                if (dp[i] > maxCount) maxCount = dp[i];
            }
        }
        
        int result = 0; // 最终结果
        
        // 统计最长递增子序列的个数
        for (int i = 0; i < nums.size(); i++) {
            if (maxCount == dp[i]) result += count[i];
        }
        
        return result;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1688778.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

WAF绕过(下)

过流量检测 这里的流量检测就是在网络层的waf拦截到我们向webshell传输的数据包&#xff0c;以及webshell返回的数据 包&#xff0c;检测其中是否包含敏感信息的一种检测方式。如果是大马的情况下&#xff0c;可以在大马中添加多处判断代码&#xff0c;因此在执行大马提供的功…

设计模式12——外观模式

写文章的初心主要是用来帮助自己快速的回忆这个模式该怎么用&#xff0c;主要是下面的UML图可以起到大作用&#xff0c;在你学习过一遍以后可能会遗忘&#xff0c;忘记了不要紧&#xff0c;只要看一眼UML图就能想起来了。同时也请大家多多指教。 外观模式&#xff08;Facade&a…

【Linux】高效文本处理命令

目录 一.sort命令&#xff08;排序&#xff09; 1.语法格式 2.常用选项 3.相关示例 3.1. 3.2. 二.unip命令&#xff08;去重&#xff09; 1.语法格式 2.常用选项 3.相关示例 3.1. 3.2. 三.tr命令&#xff08;替换&#xff09; 1.语法格式 2.常用选项 3.相关示例…

如何在 Ubuntu 24.04 (桌面版) 上配置静态IP地址 ?

如果你想在你的 Ubuntu 24.04 桌面有一个持久的 IP 地址&#xff0c;那么你必须配置一个静态 IP 地址。当我们安装 Ubuntu 时&#xff0c;默认情况下 DHCP 是启用的&#xff0c;如果网络上可用&#xff0c;它会尝试从 DHCP 服务器获取 IP 地址。 在本文中&#xff0c;我们将向…

MySQL主从复制(二):高可用

正常情况下&#xff0c; 只要主库执行更新生成的所有binlog&#xff0c; 都可以传到备库并被正确地执行&#xff0c; 备库就能达到跟主库一致的状态&#xff0c; 这就是最终一致性。 但是&#xff0c; MySQL要提供高可用能力&#xff0c; 只有最终一致性是不够的。 双M结构的…

2024年甘肃特岗教师招聘报名流程,速速查收哦!

2024年甘肃特岗教师招聘报名流程&#xff0c;速速查收哦&#xff01;

WXML模板语法-事件绑定

一、 1.事件 事件是渲染层到逻辑层的通讯方式&#xff0c;通过事件可以将用户在渲染层产生的行为&#xff0c;反馈到逻辑层进行业务的处理 2.小程序中常用的事件 3.事件对象的属性列表 当事件回调触发的时候&#xff0c;会收到一个事件对象event&#xff0c;其属性为&#x…

Mysql之基本架构

1.Mysql简介 mysql是一种关系型数据库&#xff0c;由表结构来存储数据与数据之间的关系&#xff0c;同时为sql(结构化查询语句)来进行数据操作。 sql语句进行操作又分为几个重要的操作类型 DQL: Data Query Language 数据查询语句 DML: Data Manipulation Language 添加、删…

axios案例应用

1、Spring概述 Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架&#xff0c;以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核&#xff0c;提供了展现层 Spring MVC 和持久层。Spring JDBC 以及业务层事务管理等众多…

C++进阶:C++11(列表初始化、右值引用与移动构造移动赋值、可变参数模版...Args、lambda表达式、function包装器)

C进阶&#xff1a;C11(列表初始化、右值引用与移动构造移动赋值、可变参数模版…Args、lambda表达式、function包装器) 今天接着进行语法方面知识点的讲解 文章目录 1.统一的列表初始化1.1&#xff5b;&#xff5d;初始化1.2 initializer_listpair的补充 2.声明相关关键字2.1a…

STM32——DAC篇(基于f103)

技术笔记&#xff01; 一、DAC简介&#xff08;了解&#xff09; 1.1 DAC概念 传感器信号采集改变电信号&#xff0c;通过ADC转换成单片机可以处理的数字信号&#xff0c;处理后&#xff0c;通过DAC转换成电信号&#xff0c;进而实现对系统的控制。 1.2 DAC的特性参数 1.3…

amis-editor 低代码可视化编辑器开发 和 使用说明

1.amis-editor可视化编辑器 React版本&#xff08;推荐&#xff09;&#xff1a; GitHub - aisuda/amis-editor-demo: amis 可视化编辑器示例 https://aisuda.github.io/amis-editor-demo 建议使用react版本&#xff0c;好维护&#xff0c;升级版本更新package.json中对应版本…

Property xxx does not exist on type ‘Window typeof globalThis‘ 解决方法

问题现象 出现以上typescript警告&#xff0c;是因为代码使用了window的非标准属性&#xff0c;即原生 window 对象上不存在该属性。 解决办法 在项目 根目录 或者 src目录 下新建 xxx.d.ts 文件&#xff0c;然后进行对该 属性 进行声明即可。 注意&#xff1a;假如xxx.d.ts文…

【vue】封装的天气展示卡片,在线获取天气信息

源码 <template><div class"sen_weather_wrapper"><div class"sen_top_box"><div class"sen_left_box"><div class"sen_top"><div class"sen_city">山东</div><qctc-time cl…

【Text2SQL 经典模型】X-SQL

论文&#xff1a;X-SQL: reinforce schema representation with context ⭐⭐⭐⭐ Microsoft, arXiv:1908.08113 X-SQL 与 SQLova 类似&#xff0c;使用 BERT style 的 PLM 来获得 representation&#xff0c;只是融合 NL question 和 table schema 的信息的方式不太一样&#…

Keil MDK map文件学习笔记

Keil MDK map文件学习笔记 map文件组成1.Section Cross References段交叉引用2.Removing Unused input sections from the image移除无用的段3.Image Symbol Table镜像符号表局部符号表全局符号表 4.Memory Map of the image镜像存储器映射ROM区执行域RAM区执行域 5. Image com…

C#学习指南:重要内容与实用技巧

学习C#编程是一段充满挑战但又非常充实的旅程。以下是我在学习过程中积累的一些经验&#xff0c;希望能对大家有所帮助。 一、掌握基础概念 类及其成员 C#中的类是编程的基础模块。理解类的结构、属性、方法和构造函数是至关重要的。每个类都有其特定的功能&#xff0c;学会如…

Milvus 使用过程中的常见问题集锦

引言 在使用Milvus的过程中&#xff0c;可能会遇到一些常见问题。这些问题可能涉及到配置、查询、数据同步等方面。 常见问题 以下是一些可能遇到的常见问题及其解决方法&#xff1a; 查询结果不正确&#xff1a; 可能原因&#xff1a;Milvus内部缓存与数据不一致&#xff0…

【数据结构】哈夫曼树和哈夫曼编码

一、哈夫曼树 1.1 哈夫曼树的概念 给定一个序列&#xff0c;将序列中的所有元素作为叶子节点构建一棵二叉树&#xff0c;并使这棵树的带权路径长度最小&#xff0c;那么我们就得到了一棵哈夫曼树&#xff08;又称最优二叉树&#xff09; 接下来是名词解释&#xff1a; 权&a…

APISIX-简单使用

APISIX-简单使用 这个工具还是很不错的&#xff0c;可视化的配置很清晰 &#xff0c; 想用NGINX的配置模式也是可以的&#xff0c;就是要去修改配置文件了。 APISIX&#xff0c;一个很不错的可视化工具&#xff0c;用来代替Nginx相当不错&#xff0c;可作为Nginx的平替方案&…