代码随想录打卡—day57—【回文问题】— 9.2+9.3 回文问题+DP-END

news/2025/2/12 12:14:37/

1 647. 回文子串

647. 回文子串 

【解法1】纯暴力解法,应该是O(n^3),居然AC了:

class Solution {
public:int countSubstrings(string s) {// 暴力int cnt = 0;cout << s.substr(1,1);for(int i = 0; i < s.size();i++){for(int j = i; j < s.size();j++){   string tmp = s.substr( i , (j-i+1));  // 为O(len)string reverse1 = tmp;reverse(tmp.begin(), tmp.end());  if(reverse1 == tmp)cnt++;}}return cnt;}
};

【解法2】动态规划。我按照经验的dp数组含义写,写不出,看了题解才懂。本题的dp数组和以往的不太一样,要回到回文串的本质,判断回文串的方法——当 [i,j] 确定是一个回文串时候,若i-1和j+1对应的字符一样,则可判断是一个回文串。

详见注释,AC代码:

class Solution {
public://int dp[1010]; // dp[i] 以i结尾的连续的字符串是回文子串的最大个数==>组合数目【错误】bool dp[1010][1010]; // dp[i][j]表示 s[i,j] 是一个回文串/*j >= iif(s[i] != s[j])dp[i][j] = 0;else{if(i == j) // 一个元素dp[i][j] = 1;else{if(j == i+1)dp[i][j] = 1;  //两个元素else  //至少3个元素{if(dp[i+1][j-1])dp[i][j] = 1;}}}初始化 dp[i][j] = 0;顺序:需要左下角是满的 i-- j++模拟——*/int countSubstrings(string s) {int ans = 0;for(int i = s.size()-1; i >= 0; i--){for(int j = i; j < s.size();j++){if(s[i] != s[j])dp[i][j] = 0;else{if(i == j) // 一个元素{dp[i][j] = 1;ans++;}else{if(j == i+1){dp[i][j] = 1;  //两个元素ans++;}else  //至少3个元素{if(dp[i+1][j-1]){dp[i][j] = 1;ans++;}}}}}}return ans;}
};

【解法3】双指针法。O(n^2)。

首先确定回文串,就是找中心然后向两边扩散看是不是对称的就可以了。

在遍历中心点的时候,要注意中心点有两种情况

一个元素可以作为中心点,两个元素也可以作为中心点。那么有人同学问了,三个元素还可以做中心点呢。其实三个元素就可以由一个元素左右添加元素得到,四个元素则可以由两个元素左右添加元素得到。所以我们在计算的时候,要注意一个元素为中心点和两个元素为中心点的情况。

AC代码:

class Solution {
public:int count(string s,int l,int r){int ans = 0;while(l >= 0 && r < s.size() && s[l] == s[r]){l--;r++;ans++;}return ans;}int countSubstrings(string s) {int ans = 0;for(int i = 0; i < s.size();i++){// 以i为单点中心ans += count(s,i,i);// 以i为双点中心的左中心ans += count(s,i,i + 1);}return ans;}
};

5. 最长回文子串 (类似的题)

用中心扩展双指针的做法:

class Solution {
public:int ans = 0;int max_l,max_r = 0;void count(string s,int l,int r){while(l >= 0 && r < s.size() && s[l] == s[r]){l--;r++;}l++;r--;if(r-l+1 > ans){max_l = l;max_r = r;ans = r-l+1 ;}}string longestPalindrome(string s) {for(int i = 0; i < s.size();i++){// 以i为单点中心count(s,i,i);// 以i为双点中心的左中心count(s,i,i + 1);}return s.substr(max_l,max_r - max_l + 1);}
};

2 516. 最长回文子序列

516. 最长回文子序列

我在学习完上一题的基础上,直接尝试推导这一题,因为我错误的dp数组含义:以i开头 j结尾的回文子序列的最大长度。结果状态转移方程弄的很复杂。还嵌套两个for循环。应该是能过很多测试点的,在第65个测试点 TLE 了。代码如下:

class Solution {
public:int dp[1010][1010]; // 以i开头 j结尾的回文子序列的最大长度/*if(s[i] != s[j])dp[i][j] = 0else{if(i == j)dp[i][j] = 1;   //一个元素else if(j == i+1)dp[i][j] = 2;   //两个元素else                             //至少三个元素 {int tmp = 0;for(int k1 = i+1; k1 <= j-1; k1++){for(int k2 = k1; k2<= j-1; k2++){tmp = max(tmp,dp[k1][k2]);}}if(tmp == 0)dp[i][j] = 0;else dp[i][j] = tmp+2;}}初始化:默认为0顺序:i--j++模拟:*/int longestPalindromeSubseq(string s) {int ans = 0;for(int i = s.size()-1; i >= 0; i--){for(int j = i; j < s.size();j++){if(s[i] != s[j])dp[i][j] = 0;else{if(i == j)dp[i][j] = 1;   //一个元素else if(j == i+1)dp[i][j] = 2;   //两个元素else                             //至少三个元素 {int tmp = 0;for(int k1 = i+1; k1 <= j-1; k1++)for(int k2 = k1; k2<= j-1; k2++)tmp = max(tmp,dp[k1][k2]);if(tmp == 0)dp[i][j] = 0;else dp[i][j] = tmp+2;}}ans = max(ans,dp[i][j]);}}return ans;}
};

学习完题解,要把dp数组的含义改成:以[i,j]中的回文子序列的最大长度。然后状态转移方程就比较好推导了。

AC代码:

class Solution {
public:int dp[1010][1010]; // 以[i,j]中的回文子序列的最大长度/*if(s[i] == s[j])dp[i][j] = dp[i+1][j-1] + 2;else{dp[i][j] = max(dp[i+1][j],dp[i][j-1]);去掉j元素   去掉i元素}初始化:默认为0,所以正对角线上全设置为1 ,便于状态转移的j循环从i+1开始顺序:i--j++模拟:*/int longestPalindromeSubseq(string s) {int ans = 1;for(int i = 0; i < s.size();i++)dp[i][i] = 1;for(int i = s.size()-1; i >= 0; i--){for(int j = i+1; j < s.size();j++){if(s[i] == s[j])dp[i][j] = dp[i+1][j-1] + 2;elsedp[i][j] = max(dp[i+1][j],dp[i][j-1]);ans = max(ans,dp[i][j]);}}return ans;}
};

DP总结

go to


http://www.ppmy.cn/news/1084088.html

相关文章

「黄钊的AI日报·第一季」免费试读!最后5天,早鸟价60元~

1、每天5条AI内容点&#xff1a;不是常见的新闻汇总模式&#xff0c;而是站在AI产品经理的视角&#xff0c;把每篇AI干货的最核心内容&#xff0c;直接拎出来、甚至用自己的话来描述&#xff0c;是在展示“what I see”&#xff0c;和原文已经不是一个东西了&#xff01; 2、已…

Java经典面试题(异或运算)

不爱生姜不吃醋⭐️⭐️⭐️ &#x1f33b;如果本文有什么错误的话欢迎在评论区中指正哦&#x1f497; &#x1f33b;看完之后觉得不错的话麻烦动动小手点个赞赞吧&#x1f44d; &#x1f33b;与其明天开始&#xff0c;不如现在行动&#xff01;&#x1f4aa; &#x1f33b;大家…

Elasticsearch文档多个输入字段组成ID实现方法

1、场景描述&#xff1a; 使用Elasticsearch时&#xff0c;有时会需要指定文档id的场景&#xff0c;当文档id需要多个字段组成时&#xff0c;这种业务怎么处理呢&#xff1f; 2、问题描述&#xff1a; 现有一个ElasticSearch文档&#xff0c;假设文档id由userid、 eventTime…

什么是分布式系统?

分布式系统是由多个独立的计算机或计算节点组成的系统&#xff0c;这些节点通过消息传递或共享数据的方式进行协调和通信&#xff0c;以实现共同的目标。分布式系统的设计目标是提高系统的可靠性、可扩展性、性能和容错性。 在一个分布式系统中&#xff0c;各个计算机节点之间…

golang操作数据库--gorm框架、redis

目录 1.数据库相关操作(1)非orm框架①引入②初始化③增删改查 (2) io版orm框架 (推荐用这个)①引入②初始化③增删改查④gorm gen的使用 (3) jinzhu版orm框架①引入②初始化③增删改查 2.redis(1)引入(2)初始化①普通初始化②v8初始化③get/set示例 1.数据库相关操作 (1)非orm…

给视频添加背景图片,让它们更具魅力!

想要让你的视频更加出彩吗&#xff1f;给它们添加背景图片是不错的选择&#xff01;但是&#xff0c;如何做到呢&#xff1f;不用担心&#xff0c;我们的视频剪辑高手可以帮助你轻松实现&#xff01;我们提供多种背景图片选择&#xff0c;你可以根据自己的喜好和需求进行选择。…

博客系统自动化测试项目实战(测试系列9)

目录 前言&#xff1a; 1.博客前端页面测试用例图 2.测试用例的代码实现 2.1登录页面的测试 2.2博客列表页面的测试 2.3写博客测试 2.4博客详情页面的测试 2.5已发布博客的标题和时间的测试 2.6注销用户的测试 结束语&#xff1a; 前言&#xff1a; 之前小编给大家讲…

Lodash库

Lodash库 1.简介 Lodash 是一个 JavaScript 工具库&#xff0c;提供了许多实用的函数和方法&#xff0c;用于简化 JavaScript 编程的常见任务&#xff0c;例如数组操作、对象操作、函数处理、字符串处理、事件处理等。Lodash 提供了跨浏览器兼容性的工具函数&#xff0c;能够…