动态规划算法OJ刷题(3)

news2024/12/24 20:29:03

CC19 分割回文串-ii

问题描述

给出一个字符串s,分割s使得分割出的每一个子串都是回文串。计算将字符串s分割成回文串的最小切割数。例如:给定字符串s=“aab”,返回1,因为回文分割结果[“aa”,“b”]是切割一次生成的。

解题思路

方法1:用一维数组来完成,O(N^3)

注意转移方程必须是让两个相邻状态之间一步完成。

  • 状态方程F(i) : 到第i个字符所需要的最小分割次数
  • 状态转移方程 : j<i && str[j+1, i]是回文串,若F(i)=0【表示从第1个字符到第i个字符是回文串】F(i, j) = min(F(j) + 1)
  • 初始条件 : F(i) = i - 1 ==> F(1) = 0。即单个字符只需要切0次,因为单子符都为回文串,2个字符最大需要1次,3个2次…【因为状态转移方程中要取min,那么F(i)要给一个最大的分割次数i-1】
  • 返回结果 : F(s.size())

此题i = 0是无效状态。

在这里插入图片描述

//时间复杂度O(N^3)
class Solution {
  public:
    /**
     *
     * @param s string字符串
     * @return int整型
     */

    bool isPal(string& str, int start, int end) {
        while (start < end) {
            if (str[start] != str[end]) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

    int minCut(string s) {
        // write code here
        int len = s.size();
        if (0 == len) return 0;
        
        //先判断整体是不是回文串
        if (isPal(s, 0, len-1)) return 0;

        vector<int> ret(len + 1);
        //初始条件
        for (int i = 1; i <= len; ++i) {
            ret[i] = i - 1;
        }
        //状态转移方程
        for (int i = 2; i <= len; ++i) {
            //先判断整体是不是回文串
            if (isPal(s, 0, i - 1)) {
                ret[i] = 0;
                continue;
            }
            //j<i && str[j, i-1]是回文串
            for (int j = 1; j < i; ++j) {
                if (isPal(s, j, i - 1)) {
                    ret[i] = min(ret[i], ret[j] + 1);
                }
            }
        }
        return ret[len];
    }
};

方法2:用空间换时间,用二维矩阵来保存是否为回文串的状态。时间复杂度O(N^2)

  • 状态方程F(i,j) : 区间[i, j]是否为回文串

  • 状态转移方程 : F(i, j) : s[i]==s[j] && F(i+1, j-1) 【如果字符串的首尾相同,就缩小范围再判断】

    需特殊处理:1个字符 i==j,F(i,j): true; 两个字符 i+1=j, F(i,j): s[i] == s[j]

  • 初始条件 : i==j,F(i,j): true

  • 返回结果 : F(s.size())

class Solution {
  public:
    /**
     *
     * @param s string字符串
     * @return int整型
     */

    bool isPal(string& str, int start, int end) {
        while (start < end) {
            if (str[start] != str[end]) {
                return false;
            }
            start++;
            end--;
        }
        return true;
    }

    vector<vector<bool>> getMat(string& s) {
        int n = s.size();
        vector<vector<bool>> Mat(n, vector<bool>(n, false));
        for (int i = n - 1; i >= 0; --i) {
            for (int j = i; j < n; j++) {
                if (j == i) Mat[i][j] = true;
                else if (j == i + 1) Mat[i][j] = (s[i] == s[j]);
                else Mat[i][j] = (s[i] == s[j] && Mat[i + 1][j - 1]);
            }
        }
        return Mat;
    }

    int minCut(string s) {
        int len = s.size();
        if (0 == len) return 0;
        //先判断整体是不是回文串
        if (isPal(s, 0, len - 1)) return 0;

        vector<vector<bool>> Mat = getMat(s);
        vector<int> ret(len + 1);
        for (int i = 0; i <= len; ++i) {
            ret[i] = i - 1;
        }

        for (int i = 2; i <= len; ++i) {
            for (int j = 0; j < i; ++j) {
                if (Mat[j][i - 1])
                    ret[i] = min(ret[i], ret[j] + 1);
            }
        }
        return ret[len];
    }
}

CC77 编辑距离

题目描述

给定两个单词word1和word2,请计算将word1转换为word2至少需要多少步操作。你可以对一个单词执行以下3种操作:a)在单词中插入一个字符;b)删除单词中的一个字符;c)替换单词中的一个字符。

就是指从1个字符串转成另一个字符串所需的最少编辑操作次数

解题思路

子问题:从word1的第i个字符到word2的第j个字符需要的操作距离

通过状态方程,可知

1、F(i, j-1)–>F(i,j):word1[1,i]、word2[1,j-1]==>word1[1,i]==word2[1,j],字符1的前i个字符和字符2的前j-1个字符,通过对字符2进行1次插入第j个字符操作,使得字符1的前i个字符和字符2前j个字符相等;

2、F(i-1, j) -->F(i,j):word1[1,i-1]、word2[1,j]==>word1[1,i]==word2[1,j],字符1的前i个字符和字符2的前j-1个字符,通过对字符1进行1次删除第i个字符的操作,使得字符1的前i个字符和字符2前j个字符相等;

3、F(i-1, j-1)–>F(i,j):当word1[i]!=word2[j]时,才需要此操作。word1[1,i-1]、word2[1,j-1]==>word1[1,i]==word2[1,j],通过对字符1的第i个字符进行1次替换操作,使得字符1的前i个字符和字符2前j个字符相等;

  • 状态方程F(i,j) : 字符1前i个字符到字符2前j个字符的编辑距离
  • 状态转移方程 : F(i, j) = min(F(i, j-1) + 1, F(i-1, j) + 1, F(i-1, j-1) + (word1[i]==word2[j]) ? 0 : 1))【1、F(i, j-1) + 1 = F(i, j); 2、F(i-1, j) + 1 = F(i, j); 3、F(i-1, j-1) + (word1[i]==word2[j]) ? 0 : 1) = F(i, j);】
  • 初始条件 : F(i,0)=j; F(0,j)=i;
  • 返回结果 : F[row] [col]
#include <vector>
class Solution {
  public:
    /**
     *
     * @param word1 string字符串
     * @param word2 string字符串
     * @return int整型
     */
    int minDistance(string word1, string word2) {
        // write code here
        int row = word1.size();
        int col = word2.size();

        vector<vector<int>> minD(row + 1, vector<int>(col + 1));
        //初始化
        for (int i = 0; i <= col; ++i) minD[0][i] = i;
        for (int i = 1; i <= row; ++i) minD[i][0] = i;

        for (int i = 1; i <= row; ++i) {
            for (int j = 1; j <= col; ++j) {
                //删除 删除
                minD[i][j] = min(minD[i][j - 1], minD[i - 1][j]) + 1;
                //替换
                if (word1[i - 1] == word2[j - 1]) minD[i][j] = min(minD[i][j],
                            minD[i - 1][j - 1]);
                else minD[i][j] = min(minD[i][j], minD[i - 1][j - 1] + 1);
            }
        }
        return minD[row][col];
    }
};

在这里插入图片描述

CC36 不同的子序列

题目描述

给定两个字符串S和T,返回S子序列等于T的不同子序列个数有多少个?字符串的子序列是由原来的字符串删除一些字符(也可以不删除)在不改变相对位置的情况下的剩余字符。例如,"ACE"是"ABCDE"的子序列,但是"AEC"不是;S=“nowcccoder”, T = “nowccoder” , 返回3【now+ccoder/nowc+coder/nowcc+oder】;S=“rabbbit”, T = “rabbit” , 返回3【ra+bbit/rab+bit/rabb+it】;

解题思路

子问题:S的前i个字符构成的子串与T的前j个字符相同的子序列的个数

子串的长度要大于等于T的长度才能找到有相同的子串。

  • 状态方程F(i,j) : S的前i个字符已经与T的前j字符相同了

  • 状态转移方程 :

    在F(i,j)处需要考虑S[i] = T[j] 和 S[i] != T[j]两种情况:

    ​ 当S[i] = T[j]: 1、 让S[i]匹配T[j],则F(i,j) = F(i-1,j-1); 2、让S[i]不匹配T[j], 则问题就变为S[1:i-1]中的子串与T[1:j]相同的个数,则F(i,j) = F(i-1,j) , 故S[i] = T[j]时,F(i,j) = F(i-1,j-1) + F(i-1,j)

    ​ 当S[i] != T[j]: 问题退化为S[1:i-1]中的子串与T[1:j]相同的个数,故,S[i] != T[j]时,F(i,j) = F(i-1,j)

  • 初始条件 : F(i,0) = 1 —> S的子串与空串相同的个数,只有空串与空串相同

  • 返回结果 : F(S.size(), T.size())

class Solution {
  public:
    /**
     *
     * @param S string字符串
     * @param T string字符串
     * @return int整型
     */
    int numDistinct(string S, string T) {
        // write code here
        int s_size = S.size();
        int t_size = T.size();
        // S的长度小于T长度,不可能含有与T相同的子串
        if (S.size() < T.size()) return 0;
        // T为空串,只有空串与空串相同,S至少有一个子串,它为空串
        if (T.empty()) return 1;
        // F(i,j),初始化所有的值为0
        vector<vector<int> > f(s_size + 1, vector<int>(t_size + 1, 0));
        // 空串与空串相同的个数为1
        f[0][0] = 1;
        for (int i = 1; i <= s_size; ++i) {
            // F(i,0)初始化
            f[i][0] = 1;
            for (int j = 1; j <= t_size; ++j) {
                // S的第i个字符与T的第j个字符相同
                if (S[i - 1] == T[j - 1]) {
                    f[i][j] = f[i - 1][j] + f[i - 1][j - 1];
                } else {
                    // S的第i个字符与T的第j个字符不相同
                    // 从S的前i-1个字符中找子串,使子串与T的前j个字符相同
                    f[i][j] = f[i - 1][j];
                }
            }
        }
        return f[s_size][t_size];
    }
};

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

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

相关文章

计算机操作系统(第四版)第四章存储器管理—课后习题答案

1.为什么要配置层次存储器&#xff1f; &#xff08;1&#xff09;设置多个存储器可以使存储器两端的硬件能并行工作。 &#xff08;2&#xff09;采用多级存储系统,特别是Cache技术,这是一种减轻存储器带宽对系统性能影响的最佳结构方案。 &#xff08;3&#xff09;在微处理机…

《Java8实战》第5章 使用流

上一章已经体验到流让你从外部迭代转向内部迭代。 5.1 筛选 看如何选择流中的元素&#xff1a;用谓词筛选&#xff0c;筛选出各不相同的元素。 5.1.1 用谓词筛选 filter 方法&#xff0c;该操作会接受一个谓词&#xff08;一个返回boolean 的函数&#xff09;作为参数&am…

MySQL数据库:聚合函数、分组查询、约束、默认值设置、自增属性

一、聚合函数 1.聚合函数 在MySQL数据库中预定义好的一些数据统计函数。 2.count(*) 功能&#xff1a;统计结果条数。 3.sum(字段名) 功能&#xff1a;对指定字段的数据求和。 4.avg(字段名) 功能&#xff1a;对指定字段的数据求平均值。 5.max(字段名) 和 min(字段名) …

正则化的基本认识

正则化(一) 拟合与欠拟合(二) 正则化的目的(三) 惩罚项&#xff08;3.1&#xff09;常用的惩罚项&#xff1a;&#xff08;3.2&#xff09;L-P范数&#xff1a;&#xff08;3.3&#xff09;L1与L2的选择&#xff1a;(一) 拟合与欠拟合 欠拟合&#xff1a; 是指测试级与训练集都…

docker目录映射

docker 常用命令 docker ps // 查看所有正在运行容器 docker stop containerId // containerId 是容器的ID docker ps -a // 查看所有容器 $ docker ps -a -q // 查看所有容器ID docker stop $(docker ps -a -q) // stop停止所有容器 docker rm $(docker ps -a -q) // remove删…

受害者有罪论——如何反驳

目录 一、那些「受害者有罪论」的说法 二、「受害者有罪论」的潜台词 三、如何反驳 反驳1&#xff1a;让受害者有罪论者感同身受 反驳2&#xff1a;说理 反驳3&#xff1a; 直接指出结论的错误 反驳4&#xff1a;与对方无关&#xff0c;不用多费唇舌 四、罪犯就是罪犯&…

golang-gin框架入门

基础 快速入门 gin完整支持路由框架支持全局异常&#xff08;错误&#xff09;处理内置渲染高可扩展 组件 在gin框架中四个基本组件是&#xff1a; Engine&#xff1a;是web server的根数据结构&#xff0c;也是基础容器&#xff1b;它包含复用器、中间件和配置设置。类似S…

GC 垃圾回收算法、垃圾回收器及 JVM 调优【JVM知识点-resu】

JVM知识点 详情请见&#xff1a;垃圾回收算法、垃圾收集器详情请见&#xff1a;JVM调优 1 GC垃圾回收算法 众所周知&#xff0c;Java的内存管理是交由了JVM&#xff0c;那么程序时时刻刻都在产生新对象&#xff0c;为了避免内存溢出&#xff0c;此时必然会涉及到垃圾回收&…

【MySQL数据库原理】Python3.7 中连接 MySQL 数据库

目录 1、安装mysql-connector-python2、连接 MySQL 数据库3、修改数据库1、安装mysql-connector-python 要在 Python 中连接 MySQL 数据库 “test”,可以使用 “mysql-connector-python” 包。首先,确保已经安装了该包。可以使用 pip 命令进行安装: pip install mysql-con…

[abc复盘] abc297 20230409

[atc复盘] abc297 20230409 一、本周周赛总结A - Double Click1. 题目描述2. 思路分析3. 代码实现B - chess9601. 题目描述2. 思路分析3. 代码实现C - PC on the Table1. 题目描述2. 思路分析3. 代码实现D - Count Subtractions1. 题目描述2. 思路分析3. 代码实现E - Kth Takoy…

Spring 04 -SpringAOP开发

SpringAOP开发SpringAOP1 原理2 动态代理2.1 JDK动态代理2.2.2 Cglib动态代理2.2.3 **JDK动态代理和Cglib动态代理**3 SpringAOP3.1 AOP专业术语3.2 环境搭建3.3 基于XML配置3.4 基于注解配置2.5 通知类型面向切面编程&#xff0c;在不修改源代码的情况加&#xff0c;对类功能实…

人工智能中的顶级会议

当搭建好了AI领域的知识架构&#xff0c;即具备了较好的数学、编程及专业领域知识后&#xff0c;如果想在AI领域追踪前沿研究&#xff0c;就不能再只看教材了。毕竟AI领域的发展一日千里&#xff0c;教材上的知识肯定不是最新的。此时&#xff0c;应该将关注的重点转向AI领域的…

JavaWeb - Web网站的组成,工作流程以及开发模式

一. Web Web&#xff1a;全球广域网&#xff0c;也称玩万维网(www Wrold Wide Web)&#xff0c;就是能够通过浏览器访问的网站学习Web开发&#xff0c;其实就是要使用Java这门语言来开发这样的Web网站&#xff0c;这也是现在Java语言最主流的企业级应用方式。使用Java语言开发…

Nginx基本配置 Nginx服务基础Nginx访问控制Nginx虚拟主机

本章结构 Nginx服务基础 Nginx访问控制 Nginx虚拟主机 原理&#xff1a; 关于Nginx 一款高性能、轻量级Web服务软件 稳定性高 系统资源消耗低 apache多线程或多进程实现连接&#xff08;多线程比多线程稍微好些&#xff0c;切换资源浪费少&#xff09; Nginx单线程 对HTTP并发…

自己动手写CPU——第二篇

1 ori指令说明 ori是进行逻辑 或 运算的指令&#xff0c;其指令格式如下所示 从以上的指令格式&#xff0c;我们可以直到&#xff0c;这是一个I类型指令&#xff0c;ori指令的指令码是 6‘b001101&#xff0c;所以当处理器发现正在处理的指令的高6bit 是 001101 的时候&#x…

vue3 css相关知识与动态style

scoped 当 <style> 标签带有 scoped attribute 的时候&#xff0c;它的 CSS 只会影响当前组件的元素&#xff0c;和 Shadow DOM 中的样式封装类似。 <style scoped lang"scss"> </style> 注意 &#xff1a; 作用域样式并没有消除对 class 的需求…

DN-DETR源码学习记录

DN-DETR是在DAB-DETR的基础上完成的&#xff0c;DN-DETR的作者认为导致DETR类模型收敛慢的原因在于匈牙利匹配所导致的二义性&#xff0c;即匈牙利算法匹配的离散性和模型训练的随机性&#xff0c;导致ground-truth的匹配变成了一个动态的、不稳定的过程。举个例子&#xff0c;…

字节青训营(前端)打卡day01_计网

计算机网络概论 1.前沿和课程介绍 自顶向下、自底向上 网络分层、网络协议、网络应用、HTTP123、CDN GPT. 计算机网络的发展历程可以分为四个阶段&#xff1a;单机、局域网、广域网、互联网 2.蟹堡王帝国 顾客&#xff1a;客户端 分店&#xff1a;服务端 小区转发点&…

【FFmpeg】编码器流程分析

目录1 编译2 调用关系2.1 第一帧没有获取到码流&#xff0c;第二帧获取到一帧码流2.2 送帧为NULL&#xff0c;刷新编码器获取剩余的全部码流3 总结4 感受1 编译 参考文件doc/examples/encode_video.c&#xff0c;使用x264作为编码器&#xff0c;需要先安装x264&#xff0c;编译…

如何用ChatGPT写毕业论文?

老早之前就听说有同学用ChatGPT写论文了 但是一直不觉得人工智能够真的替代人类 正好最近毕业论文开始降重了&#xff0c;超高的重复率愁得我快睡不着了 刷微博突然看到这个有关ChatGPT的问题。 出于好奇的我决定先来试试这个ChatGPT到底能不能帮我解决降重问题哈哈哈 点击…