【LeetCode】5.最长回文子串 Longest Palindromic Substring

5. Longest Palindromic Substring

 Given a string s, find the longest palindromic substring in s. 
 You may assume that the maximum length of s is 1000.

Example 1:

Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.

Example 2:

Input: "cbbd"
Output: "bb"

解法一: 枚举 + 贪心

枚举出所有子串,判断其是不是回文串,我们可以从最长的子串开始枚举,如果发现是回文串,就可以立马返回。

bool isPalindrome(string s) {
  int len = s.size();
  for (int i = 0; i < len; i++) {
    if (s[i] != s[len - i - 1]) return false;
  }
  return true;
}

string longestPalindrome(string s) {
  int len = s.size();
  if (len < 2) return s;
  for (int i = 0; i < len; i++) {
    for (int j = 0; j <= i; j++) {
      string str1 = s.substr(j, len - i);
      if (isPalindrome(str1)) {
        return str1;
      }
    }
  }
  return s.substr(0, 1);
}

这样做的结果就是时间复杂度几乎高达O(n^3),只能过部分数据。

所以可以改进一下:
在上面的代码中我们每次都调用了substr方法,其实可以不用真的构造出一个子串,接下来我们改造一下 isPalindrome 函数

bool isPalindrome(string &s, int start, int end) {
  for (int i = start; i <= end; i++) {
    if (s[i] != s[end - i + start]) return false;
  }
  return true;
}

string longestPalindrome(string s) {
  int len = s.size();
  if (len < 2) return s;
  for (int i = 0; i < len; i++) {
    for (int j = 0; j <= i; j++) {
      if (isPalindrome(s, j, j + len - i - 1)) {
        return s.substr(j, len - i);
      }
    }
  }
  return s.substr(0, 1);
}

经过这个优化之后,试了一下,可以通过。

能不能再快一点?

解法二:动态规划 O(n^2)

dp[i][j] = 1 表示子串s[i…j]是回文串;

那么当s[i - 1] == s[j + 1], 则dp[i - 1][j + 1]也是回文串;

i代表子串长度,j代表子串头部的位置;

我们从小到大枚举子串,当判断较长的子串s[j…i]时,

只需要判断首尾是否相等,如果相等且dp[j + 1][j + i - 1 - 1] == 1,那么就可以得出 dp[j][j + i - 1] = 1;

这样,当枚举完所有子串时,就能得出最长回文子串的长度啦

string longestPalindrome(string s) {
  if (s.size() < 2) return s;
  int len = s.size();
  int dp[len][len];
  dp[0][0] = 1;
  for (int i = 1; i < len; i++) {
    dp[i][i - 1] = dp[i][i] = 1; // dp[i][i - 1] = 1的是为了处理长度为2的情况
  }
  int start = 0, maxLen = 0;
  for (int i = 2; i <= len; i++) {
    for (int j = 0; j <= len - i; j++) {
      if (s[j] == s[j + i - 1] && dp[j + 1][j + i - 2]) {
        dp[j][j + i - 1] = 1;
        if (i > maxLen) {
          maxLen = i;
          start = j;
        }
      }
    }
  }
  return s.substr(start, maxLen);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LeetCode是一个非常受欢迎的在线编程平台,提供了大量的算法题目,涵盖了各种难度级别和题型。下面是一些常用的LeetCode算法: 1. 两数之和(Two Sum):给定一个整数数组和一个目标值,找出数组中和为目标值的两个数的索引。 2. 反转字符串(Reverse String):反转给定字符串中的字符顺序。 3. 最长公共前缀(Longest Common Prefix):找出一组字符串中最长的公共前缀。 4. 合并两个有序链表(Merge Two Sorted Lists):将两个有序链表合并为一个新的有序链表。 5. 有效的括号(Valid Parentheses):判断给定的字符串中的括号是否有效。 6. 盛最多水的容器(Container With Most Water):给定一组非负整数,表示一组垂直线在x轴上的坐标,找出两条线与x轴组成的容器可以容纳的最大水量。 7. 三数之和(3Sum):给定一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a + b + c = 0。 8. 最长回文子串Longest Palindromic Substring):找出给定字符串中的最长回文子串。 9. 二叉树的最大深度(Maximum Depth of Binary Tree):计算二叉树的最大深度,即从根节点到最远叶子节点的最长路径上的节点数。 10. 两个排序数组的中位数(Median of Two Sorted Arrays):给定两个大小为m和n的有序数组,找出这两个数组合并后的中位数。 以上只是LeetCode中的一小部分常用算法题目,LeetCode还有很多其他类型的题目,包括动态规划、回溯、贪心算法等等。如果你有具体的算法问题或者需要更多的题目推荐,请告诉我。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值