idea leetcode插件_跟我学:LeetCode刷题之5. 最长回文子串

d131dcb74f892d792cf33840c97d1d5d.png

导读

今天进行了快手Android客户端两轮的面试,三面安排在明天。每一轮都有一道算法题,第一轮是讲解一下归并排序,随手写出了完整的代码;第二轮是一个岛屿问题的同类型的问题26个字母代表26种颜色组成的二维数组存在多少个色块,解决方法有深度优先遍历dfs和并查集两种方式,手写了第一种,第二种解法的数据结构忘了而且也没让我写,就这么过了。好了上面本人两道真实算法面试题,因为都这两题都背过记过理解过,也是分分钟钟写了出来。下面这里通还是继续今天的题目吧

看题总结

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000

示例 1:

输入: "babad"输出: "bab"注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"输出: "bb"

Related Topics

字符串动态规划

通过对题目的阅读,我们可以得出以下几个结论

  • 题目类型为字符串
  • 题意为找到最长的回文字符串
  • 输入安全判断,空字符串

多解法及复杂度分析

解法一:中心扩散法

本题最容易想到的一种方法应该就是 中心扩散法

中心扩散法怎么去找回文串?

从每一个位置出发,向两边扩散即可。遇到不是回文的时候结束。举个例子,str = acdbbdaastr=acdbbdaa 我们需要寻找从第一个 b(位置为 33)出发最长回文串为多少。怎么寻找?

首先往左寻找与当期位置相同的字符,直到遇到不相等为止。

然后往右寻找与当期位置相同的字符,直到遇到不相等为止。

 public String longestPalindrome(String s) {        if (null == s || s.length() == 0) {            return "";        }        int start = 0, end = 0;        for (int i = 0; i < s.length() - 1; i++) {            int len1 = expandAroundCenter(s, i, i);            int len2 =  expandAroundCenter(s, i, i + 1); // 偶数情况            int len = Math.max(len1, len2);            if (len > end - start) {                start = i - (len - 1) / 2;  // 偶数情况                end = i + len / 2;            }        }        return s.substring(start, end + 1);    }    private int expandAroundCenter(String s, int left, int right) {        while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {            left--;            right++;        }        return right - left - 1;    }

复杂度

时间复杂度:O(n^2)

空间复杂度:O(1)

解法二:动态规划

dp[i][j] 表示 范围[i,j] 是否为回文数

  • 确定dp[i][j]是否是回文数,只需要dp[i+1][j-1]是回文数并且s[i] == s[j]即可。
  • 但是长度为0或1的回文传需要特殊处理,即j-i < 2;
  • 因为知道dp[i]需要先知道dp[i+1],所以i需要从大到小开始遍历
  • 因为知道dp[j]需要先知道dp[j-1],所以j需要从小到大开始遍历

即: dp[i][j] = s[i] == s[j] && ( dp[i+1][j-1] || j - i < 2)

public String longestPalindrome(String s) {        if (s == null || s.length() == 0) {            return "";        }        int n = s.length();        String res = "";        boolean[][] dp = new boolean[n][n];        for (int i = n - 1; i >= 0; i--) {            for (int j = i; j < s.length(); j++) {                dp[i][j] = s.charAt(i) == s.charAt(j) && (j - i < 2 || dp[i + 1][j - 1]);                if (dp[i][j] && j - i + 1 > res.length()) {                    res = s.substring(i, j + 1);                }            }        }        return res;    }

技巧与心得

  1. 开一个github仓库用来记录各种题解
  2. 在idea或者vscode中都提供了leecode的插件刷题,方便调试断走流程
  3. 遇到不会的题不要慌,稳住心态直接看题解
  4. 文字类的表述不如视图类的直观,图文并茂精选图解优先或者参考leetcode国际站的大牛题解
  5. 图解依旧看着吃力也无妨,可以在哔哩哔哩或者YouTube上,通过leecode + 题号,搜索高收视率的视频观看
  6. 多看几次本文跟我学:LeetCode刷题大法,相信我你肯定能越刷越自信

最后的最后

看到最后,我相信你对本题应该有不一样的感受了吧!在此若有不对之处或建议等,留言告诉我;若有疑惑或者不一样的看法,也请告诉我,我们可以一起探讨学习!

我是Yangcy,该吃吃该喝喝,该学还得学,我们一起加油!

点击左下角了解更多,查看所有LeetCode优质题解代码

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值