再也不怕回文字符串的dp了

7.29面 tiktok测开一面

采用例题+自己理解的方式解决这个系列的问题

第一题:回文字符串的个数

递归五部曲:

  1. 确定dp含义,dp[i][j]是i到j是否是回文字符串
  2. 确定递推公式,

s.charAt(i)!=s.charAt(j)不用看了

s.charAt(i)==s.charAt(j):

  • "a","aa" 这一种长度小于2的肯定是的
  • "a???a" 这种只能看中间的是否是回文字符串了所以和f[i+1][j-1]有关
  1. dp数组如何初始化 都是false f[i][i]的情况上面考虑到了
  2. 递归顺序,根据地推公式,需要从左下往右上推,所以横排倒序,竖排正序

5.举例推导dp数组 6->2 9->4 10->5

java 复制代码
class Solution {
    public int countSubstrings(String s) {
        int len = s.length();
        int ans = 0;

        boolean[][] f = new boolean[len][len];

        for(int i=len-1;i>=0;i--){
            for(int j = i;j<len;j++){
                if(s.charAt(i)==s.charAt(j)){
                    if(j-i<=1){
                        f[i][j] = true;
                        ans++;
                    }else if(f[i+1][j-1]){
                        ans++;
                        f[i][j] = true;
                    }
                }
            }
        }
        return ans;
    }
}

第二题:最长回文子序列

这题相较于上面一题的不同就是递推公式d:

java 复制代码
if (s.charAt(i) == s.charAt(j)) { 
    dp[i][j] = dp[i + 1][j - 1] + 2; 
} else { 
    dp[i][j] = Math.max(dp[i + 1][j], Math.max(dp[i][j], dp[i][j - 1]));
}

这里是序列,所以 asca这个的长度也是2

如果是ascb 则需要看asc和scb的长度谁长

这里我看代码随想录还比较了

ini 复制代码
 dp[i][j] = Math.max(dp[i + 1][j], Math.max(dp[i][j], dp[i][j - 1]));

其实只要比较dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); 因为上面我们说过了遍历的顺序,这题也一样 只会遍历一遍

java 复制代码
public class Solution {
    public int longestPalindromeSubseq(String s) {
        int len = s.length();
        int[][] dp = new int[len + 1][len + 1];
        for (int i = len - 1; i >= 0; i--) { // 从后往前遍历 保证情况不漏
            dp[i][i] = 1; // 初始化
            for (int j = i + 1; j < len; j++) {
                if (s.charAt(i) == s.charAt(j)) {
                    dp[i][j] = dp[i + 1][j - 1] + 2;
                } else {
                    dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]);
                }
            }
        }
        return dp[0][len - 1];
    }
}

第三题:最长回文子串

再回头看这题 难点就是,如何确定dp数组的含义了,这题虽然是求最长的,但是还是用了boolean数组,额外维护一个最长的区间就行了。

java 复制代码
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();

        boolean[][] f = new boolean[len][len];
        int maxLen = 0, l=0, r=0;

        for(int i=len-1;i>=0;i--){
            for(int j=i;j<len;j++){
                if(s.charAt(i)==s.charAt(j)){
                    if (j - i <= 1) { // 情况一 和 情况二
                        f[i][j] = true;
                    } else if (f[i + 1][j - 1]) { // 情况三
                        f[i][j] = true;
                    }
                }
                if(f[i][j] && j-i+1>maxLen){
                    maxLen = j-i+1;
                    l = i;
                    r = j;
                }
            }
        }
        return s.substring(l,r+1);
    }
}

总结

代码还是自己敲一遍熟悉。。。。面试手撕高压环境没有熟练度和思维根本不可能做出来

相关推荐
budingxiaomoli几秒前
分治算法-快排
数据结构·算法
无知的前端9 分钟前
一文精通-Mixin特性
flutter·面试·dart
云泽80811 分钟前
C++ STL 栈与队列完全指南:从容器使用到算法实现
开发语言·c++·算法
前端小白在前进1 小时前
力扣刷题:复原IP地址
tcp/ip·算法·leetcode
yaoh.wang1 小时前
力扣(LeetCode) 94: 二叉树的中序遍历 - 解法思路
python·算法·leetcode·面试·职场和发展·二叉树·跳槽
Evand J1 小时前
【课题推荐】基于视觉(像素坐标)与 IMU 的目标/自身运动估计(Visual-Inertial Odometry, VIO),课题介绍与算法示例
人工智能·算法·计算机视觉
xu_yule1 小时前
算法基础(背包问题)—分组背包和混合背包
c++·算法·动态规划·分组背包·混合背包
1024肥宅1 小时前
现代 JavaScript 特性:ES6+ 新特性深度解析与实践
前端·javascript·面试
蓝色汪洋1 小时前
数码串和oj
数据结构·算法
努力学算法的蒟蒻1 小时前
day39(12.20)——leetcode面试经典150
算法·leetcode·面试