![d131dcb74f892d792cf33840c97d1d5d.png](https://i-blog.csdnimg.cn/blog_migrate/2b7745a4cfb93d2c48581f6520f65bac.jpeg)
导读
今天进行了快手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; }
技巧与心得
- 开一个github仓库用来记录各种题解
- 在idea或者vscode中都提供了leecode的插件刷题,方便调试断走流程
- 遇到不会的题不要慌,稳住心态直接看题解
- 文字类的表述不如视图类的直观,图文并茂精选图解优先或者参考leetcode国际站的大牛题解
- 图解依旧看着吃力也无妨,可以在哔哩哔哩或者YouTube上,通过leecode + 题号,搜索高收视率的视频观看
- 多看几次本文跟我学:LeetCode刷题大法,相信我你肯定能越刷越自信
最后的最后
看到最后,我相信你对本题应该有不一样的感受了吧!在此若有不对之处或建议等,留言告诉我;若有疑惑或者不一样的看法,也请告诉我,我们可以一起探讨学习!
我是Yangcy,该吃吃该喝喝,该学还得学,我们一起加油!
点击左下角了解更多,查看所有LeetCode优质题解代码