Leetcode 516 最长回文子序列
Posted 牛有肉
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode 516 最长回文子序列相关的知识,希望对你有一定的参考价值。
动态规划的核心是找到解题路径中的重复子问题,避免重复计算。
找出问题间的递归关系,用问题解决问题需要培养归纳的思维。
问题定义的好坏直接影响到可以定位出的重叠子问题的多少,可以找出的重叠子问题越多,问题定义越好。
下面是两种问题的定义,效率差距非常大。
解法1,超时:
public final int longestPalindromeSubseq(String s) { int re = 0; int len = s.length(); int[][] cache = new int[len + 1][len + 1]; Map<Character, Integer> map = new HashMap<Character, Integer>(); for (int i = 0; i < s.length(); i++) { map.put(s.charAt(i), i); } for (int i = 0; i < s.length(); i++) { re = Math.max(re, longestPalindromeSubseq(s, i, len, cache, map)); } return re; } /** * @Author Niuxy * @Date 2020/7/27 9:27 下午 * @Description 求最长回文子序列 * 固定头元素,区间寻找尾元素 */ private final int longestPalindromeSubseq(String s, int begin, int end, int[][] cache, Map<Character, Integer> map) { if (begin > end) { return 0; } if (begin == end - 1) { return 1; } if (cache[begin][end] != 0) { return cache[begin][end]; } //在 begin 与 end 之间找尾元素 int endIn = begin; char beginChar = s.charAt(begin); int e; if (map.containsKey(beginChar) && (e = map.get(beginChar)) < end) { endIn = e; } else { for (int i = begin + 1; i < end; i++) { if (s.charAt(begin) == s.charAt(i)) { endIn = i; } } } if (begin == endIn) { return 0; } //递归子序列 int re = 0; for (int i = begin + 1; i < endIn; i++) { re = Math.max(re, longestPalindromeSubseq(s, i, endIn, cache, map)); } re += 2; cache[begin][end] = re; return re; }
解法2:
/** * @Author Niuxy * @Date 2020/7/28 12:12 下午 * @Description 对于分治问题的定义,为了维系问题间的关系,定义必须包含头元素与尾元素 * 上一种方法固定一端在区间寻找另一端,在区间内寻找问题的递归结构 * 换一种思路,每个元素只有两个状态,选择或者不选择 * 尝试在这两个状态间切换,以此寻找问题间的递归关系 */ private final int longestPalindromeSubseq(String s, int begin, int end, int[][] cache) { if (begin == end) { return 1; } if (cache[begin][end] != 0) { return cache[begin][end]; } int re = 0; //符合回文条件,首尾必选 if (s.charAt(begin) == s.charAt(end)) { re = longestPalindromeSubseq(s, begin + 1, end - 1, cache) + 2; } else { //否则选一个,挑最长的 re = Math.max(longestPalindromeSubseq(s, begin, end - 1, cache), longestPalindromeSubseq(s, begin + 1, end, cache)); } cache[begin][end] = re; return re; } public final int longestPalindromeSubseqDP(String s) { int len = s.length(); return longestPalindromeSubseq(s, 0, len - 1, new int[len][len]); }
以上是关于Leetcode 516 最长回文子序列的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode 516 最长回文子序列[动态规划] HERODING的LeetCode之路
516 Longest Palindromic Subsequence 最长回文子序列
LeetCode 516. 最长回文子序列(区间dp) / 36. 有效的数独/73. 矩阵置零/496. 下一个更大元素 I / 456. 132 模式(特别的单调栈)