leetcode 第四题:动态规划思想的应用
来源:互联网 发布:在线询问医生软件 编辑:程序博客网 时间:2024/06/06 05:40
题目大意:给定一个字符串,找出其最长的子回文串将其返回。所谓回文串,即倒序排列与正序排列一致。
说明:假定字符串长度不超过1000
示例:输入"babad",输出"bab"或者"aba"
解题思路:关于题目有几点要注意的。一是题目默认是有解的,当输入如"abcde"的形式时,解当为"a"或者任一字符代表的字符串;二是有多个解,只需输出一个即可。
在思考这道题时,最先冒出的想法很简单,即以第一个字符为头开始,逐步增加字符串长度,判断是否为回文串。若不是,记录最大长,并跳到下一字符,以其开头。这样做虽然简单,但时间复杂度过高,很容易出现超时。
联想到之前做的一道题,我试着用“滑动窗”法去解决它。如下:
class Solution {public: string longestPalindrome(string s) { int j,k1,k2,left=0,right=0,res=0; //记录滑动窗的左右边界string ans;k1=1;k2=1;for(j=2;j<s.length();j++) //遍历字符串{if(j>=2*k1&&s.at(j)==s.at(j-2*k1)) //如果奇对称的话{if(2*k1+1>res){left=j-2*k1; //更新左右的值right=j;res=2*k1+1;}k1++;}elsek1=1;if(j>=2*k2-1&&s.at(j)==s.at(j+1-2*k2)) //如果偶对称的话{if(2*k2>res){left=j+1-2*k2;right=j;res=2*k2;}k2++;}elsek2=1;}ans=s.substr(left,res);return ans; }};思路也不复杂。从左往右逐个遍历字符串中的元素,判断该元素与之前的元素是否形成对称。若形成对称,则保留对称信息,继续遍历下一元素。此方法在本地测试时没有出现问题,但上传后结果是WA。我思考了一下,发现在编写程序时,漏掉了一种些情况。比如输入"aaaaa",结果输出"aaaa",原因在于遍历到第3个‘a’时,程序只检查了其与之前元素对称的情况,而跳过了第三个'a'中心对称的情形。另外,对于结果是单个字符的情况,也没有做处理。
在做了一定改动结果仍不正确后,我参考了solution中的答案。其中比较有代表性的就是利用动态规划的思想去解决。
在这种方法中,首先需要给出动态规划的递推式。本题中的递推式如下:
其中,
简单地说,就是用P(i,j)表示对于从下标i到j的子字符串是否为回文串,如果其是回文串,则为逻辑真,否则为逻辑假。那么对于一个回文串,如果其一前一后两个字符又相同,则可将其“扩充”成更长的回文串。基于此,只要找出给定字符串中长为1或者2的子回文串,然后对其逐个扩充至最长,记录下最长回文串的信息,返回即可。实现代码如下:
class Solution {public: string longestPalindrome(string s) {int i,j,k,t=0,palindrome[2000][2],res=0,ans=1;string ret;memset(palindrome,0,sizeof(palindrome));for(i=0;i<s.length()-1;i++) //最后一个字符单独考虑{if(s.at(i)==s.at(i+1)){palindrome[i][0]=i;palindrome[i][1]=i+1;palindrome[s.length()+t][0]=i;palindrome[s.length()+t][1]=i;t++;}else{palindrome[i][0]=i;palindrome[i][1]=i;}}palindrome[s.length()-1][0]=s.length()-1;palindrome[s.length()-1][1]=s.length()-1;for(j=0;j<s.length()+t;j++) //动态规划以扩充回文串{k=0;while(palindrome[j][1]+k<=s.length()-1&&palindrome[j][0]>=k&&s.at(palindrome[j][0]-k)==s.at(palindrome[j][1]+k))k++;if(res<k*2+(palindrome[j][0]==palindrome[j][1]?-1:0)){res=k*2+(palindrome[j][0]==palindrome[j][1]?-1:0);ans=j;palindrome[j][0]=palindrome[j][0]-k+1;palindrome[j][1]=palindrome[j][1]+k-1;}}ret=s.substr(palindrome[ans][0],res);return ret; }};值得注意的是,在编写代码时比较容易遗漏一些情形。比如输入连续重复字符时,若没有变量t,就会出现比正确结果少1的情况。
本方法的时间复杂度时O(n^2),在接受范围内。在solution中还提供了一种复杂度仅为O(n)的方法,不过由于不具有一般性,此处不赘述。
动态规划属于比较常见的处理手段,其难点在于想到以动态规划的方法去解题以及建立动态规划的关系式。希望能从这道题中引以为戒,学会更多数据处理方法。
- leetcode 第四题:动态规划思想的应用
- 动态规划的思想
- 动态规划的思想
- 动态规划的思想
- 动态规划的思想
- leetcode 第32题:动态规划思想与堆栈的灵活使用
- LeetCode || Minimum Path Sum 动态规划思想
- 动态规划的基本思想
- 动态规划的基本思想
- 动态规划思想的几个问题
- 动态规划的应用
- LeetCode Container With Most Water 查找容水量最大的容器 动态规划法思想分析
- 动态规划(DM)的基本思想
- (一)、动态规划的基本思想
- (一)、动态规划的基本思想
- Fibonacci数列的动态规划思想
- 微分动态规划的基本思想
- poj 2287 Tian Ji -- The Horse Racing 贪心思想在动态规划上的应用
- 内核同步方法
- [初学笔记]矩阵
- STVP STM8 COSMIC C编译器在WIN10上的安装使用(附安装与破解软件)
- SessionState的几种设置
- 汉字Unicode解码
- leetcode 第四题:动态规划思想的应用
- unity3d发布EXE去掉边框
- 从 Cryptoeconomics 剖析区块链背后机制
- Android开机图片替换
- JAVA实现远程控制(JAVA in RemoteControl)
- java.lang.Class类详解
- 线上操作与线上问题排查实战
- Greenplum Sequence机制
- android-edittext-validation校验器