java最长回文子序列_算法--字符串:最长回文子序列

转自:labuladong公众号

子序列问题是常见的算法问题,而且并不好解决。

首先,子序列问题本身就相对子串、子数组更困难一些,因为前者是不连续的序列,而后两者是连续的,就算穷举都不容易,更别说求解相关的算法问题了。

而且,子序列问题很可能涉及到两个字符串,比如让你求两个字符串的 最长公共子序列,如果没有一定的处理经验,真的不容易想出来。所以本文就来扒一扒子序列问题的套路,其实就有两种模板,相关问题只要往这两种思路上想,十拿九稳。

一般来说,这类问题都是让你求一个最长子序列,因为最短子序列就是一个字符嘛,没啥可问的。一旦涉及到子序列和最值,那几乎可以肯定,考察的是动态规划技巧,时间复杂度一般都是 O(n^2)。

原因很简单,你想想一个字符串,它的子序列有多少种可能?起码是指数级的吧,这种情况下,不用动态规划技巧,还想怎么着呢?

既然要用动态规划,那就要定义 dp 数组,找状态转移关系。我们说的两种思路模板,就是 dp 数组的定义思路。不同的问题可能需要不同的 dp 数组定义来解决。

一、两种思路

1、第一种思路模板是一个一维的 dp 数组:

int n =array.length;int[] dp = new int[n];for (int i = 1; i < n; i++) {for (int j = 0; j < i; j++) {

dp[i]= 最值(dp[i], dp[j] +

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们可以发现一个回文子序列中,只有两种字符出现,要么是aa,要么是bb。因此,我们可以先统计s中a和b的数量,然后分别考虑只删除a或只删除b的情况。 对于只删除a的情况,我们可以将s中所有的a删除,得到一个新的字符串s',然后判断s'是否为回文字符串,如果是,则说明只需要删除a即可,否则需要删除s'中所有的b,得到一个新的字符串s'',然后判断s''是否为回文字符串,如果是,则说明只需要删除a和b即可,否则说明无法通过只删除a来使得s成为回文字符串。 同理,对于只删除b的情况,我们也可以得到一个新的字符串s''',然后判断s'''是否为回文字符串,如果是,则说明只需要删除b即可,否则需要删除s'''中所有的a,得到一个新的字符串s'''',然后判断s''''是否为回文字符串,如果是,则说明只需要删除a和b即可,否则说明无法通过只删除b来使得s成为回文字符串。 综上所述,我们可以得到一个简单的算法: 1. 统计s中a和b的数量,分别记为na和nb 2. 如果na=0或nb=0,则说明s本身就是回文字符串,无需删除任何字符,直接返回0 3. 否则,分别考虑只删除a和只删除b的情况: 3.1 只删除a的情况: 3.1.1 将s中所有的a删除,得到一个新的字符串s' 3.1.2 如果s'是回文字符串,则返回na 3.1.3 否则,将s'中所有的b删除,得到一个新的字符串s'' 3.1.4 如果s''是回文字符串,则返回na+nb,否则返回-1 3.2 只删除b的情况: 3.2.1 将s中所有的b删除,得到一个新的字符串s''' 3.2.2 如果s'''是回文字符串,则返回nb 3.2.3 否则,将s'''中所有的a删除,得到一个新的字符串s'''' 3.2.4 如果s''''是回文字符串,则返回na+nb,否则返回-1 4. 如果以上两种情况都无法使得s成为回文字符串,则返回-1 代码如下:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值