【Day 2】公开打卡第2天 | LeetCode 5. 最长回文子串(中心扩展法) + Go slice 常见陷阱

0 阅读3分钟
  1. 今日打卡宣言(1-2句,保持真诚) Day 2,坚持住了!昨天发完第一篇后有点小成就感,今天项目虽然忙,但还是挤时间把这道经典题手写了一遍。继续拒绝温水煮青蛙,冲!

  2. LeetCode 部分 代码

5. 最长回文子串

中等

相关标签

premium lock icon相关企业

提示

给你一个字符串 s,找到 s 中最长的 回文 子串。

 

示例 1:

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。

示例 2:

输入: s = "cbbd"
输出: "bb"

 

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成
    • 题目链接:leetcode.cn/problems/lo…
    • 难度:中等
    • 时间复杂度目标:O(n²)(中心扩展法)
    • 核心思路(简短3行): 回文串以单个字符或两个字符为中心,向两边扩展检查是否相同。遍历每个可能中心(2n-1个),扩展到最大,记录最长长度和起始位置。
    • 代码(Go 版本,中心扩展法,最常用也最易懂):

Go

func longestPalindrome(s string) string {
    if len(s) < 2 {
        return s
    }
    
    start, maxLen := 0, 1  // 至少长度1
    
    // 扩展函数:从 left/right 向两边扩展
    expand := func(left, right int) (int, int) {
        for left >= 0 && right < len(s) && s[left] == s[right] {
            left--
            right++
        }
        return left + 1, right - 1  // 回退一步是有效边界
    }
    
    for i := 0; i < len(s); i++ {
        // 奇数长度回文(以i为中心)
        l, r := expand(i, i)
        if r-l+1 > maxLen {
            start = l
            maxLen = r - l + 1
        }
        
        // 偶数长度回文(以i和i+1为中心)
        l, r = expand(i, i+1)
        if r-l+1 > maxLen {
            start = l
            maxLen = r - l + 1
        }
    }
    
    return s[start : start+maxLen]
}
  • C++ 版本(如果你想双语放一个简短的):

C++

string longestPalindrome(string s) {
    if (s.size() < 2) return s;
    int start = 0, maxLen = 1;
    auto expand = [&](int l, int r) {
        while (l >= 0 && r < s.size() && s[l] == s[r]) { --l; ++r; }
        return make_pair(l+1, r-1);
    };
    for (int i = 0; i < s.size(); ++i) {
        auto [l1, r1] = expand(i, i);
        if (r1 - l1 + 1 > maxLen) { start = l1; maxLen = r1 - l1 + 1; }
        auto [l2, r2] = expand(i, i+1);
        if (r2 - l2 + 1 > maxLen) { start = l2; maxLen = r2 - l2 + 1; }
    }
    return s.substr(start, maxLen);
}
  • 易错点/优化点:

    1. expand 时 left-- 和 right++ 要在 while 判断前执行?不对,要在循环里先判断再移动。
    2. 边界:left >=0 && right < len(s) 必须同时检查。
    3. 面试追问:怎么优化到 O(n)?(Manacher 算法,但今天先掌握中心扩展)
    4. 空间:O(1),很好!
  1. 知识点部分(今天配 Go slice 陷阱,超实用) Go slice 常见陷阱 & 面试高频

    • append 时容量不足会重新分配(通常翻倍),导致旧 slice 底层数组可能被新 slice 共享。
    • 示例 bug:

Go

a := []int{1, 2, 3}
b := a[:2]          // b = [1,2], 底层数组共享
b = append(b, 4)    // 如果容量够,a 也会变成 [1,2,4,3]!!
  • 正确做法:想独立 → b := append([]int{}, a[:2]...) 或 copy
  • 面试常问:slice 是值传递还是引用?(值传递,但底层数组指针,所以修改元素会影响原 slice)
  • 容量 vs 长度:cap(s) 和 len(s) 区别,append 后 cap 可能变大。
  1. 今日感悟(最打动人的一段) 这道题以前觉得“简单”,今天从头写中心扩展才发现边界条件超级多(奇偶、起始位置记录、expand 里的 left/right 回退)。公开打卡逼着我必须跑通测试用例,不能蒙混。感觉每多写一行代码,就离舒适区远一点。继续坚持!
  2. 结束语 明天见! 欢迎评论区:① 分享你的最长回文子串写法 ② 指出我代码哪里还能优化 ③ 说说你最近刷题的痛点 #程序员打卡 #LeetCode #Go语言 #最长回文子串