Day 3 继续推进。
今天的两道题一个偏 字符串回文处理,一个偏 模拟构造
难度看起来不像昨天那样“硬”,但这两题非常适合练基本功:如何从规律中写出干净代码

今天的关键词是:中心扩散、规律模拟、边界处理


🧠 LeetCode 5 – Longest Palindromic Substring

💡 思路总结

这题要求找到字符串中的最长回文子串。

最直接的思路不是暴力枚举所有子串,而是:

👉 以每个位置为中心,向两边扩散

因为回文串有两种情况:

  • 奇数长度回文:中心是一个字符
  • 偶数长度回文:中心是两个字符之间

所以每次遍历到下标 i 时,要做两次扩展:

  • expand(s, i, i)
  • expand(s, i, i + 1)

⚡ 核心点

  • 回文的本质:左右字符相等
  • 每个位置都可能成为回文中心
  • 用辅助函数统一处理扩展逻辑,代码更清晰

💻 代码实现

class Solution {
public:
    string longestPalindrome(string s) {
        if (s.empty()) return "";

        int start = 0, maxLen = 1;

        for (int i = 0; i < s.size(); i++) {
            expand(s, i, i, start, maxLen);       // 奇数长度
            expand(s, i, i + 1, start, maxLen);   // 偶数长度
        }

        return s.substr(start, maxLen);
    }

    void expand(string& s, int left, int right, int& start, int& maxLen) {
        while (left >= 0 && right < s.size() && s[left] == s[right]) {
            if (right - left + 1 > maxLen) {
                maxLen = right - left + 1;
                start = left;
            }
            left--;
            right++;
        }
    }
};

📌 知识点总结

1️⃣ 中心扩展法

相比暴力枚举所有子串,这种方法更自然:

  • 枚举中心
  • 向两边扩展
  • 实时更新最长长度

时间复杂度是 O(n^2),空间复杂度是 O(1)


2️⃣ 回文串的两种中心

这题最容易漏掉的点就是:

  • "aba" 是奇数回文
  • "abba" 是偶数回文

所以一定要写两次扩展。


3️⃣ 辅助函数思想

把“扩散逻辑”单独写成 expand,好处很明显:

  • 主函数更清晰
  • 逻辑复用
  • 更不容易写乱

这也是以后写题时很值得保留的习惯。


🔀 LeetCode 6 – Zigzag Conversion

💡 思路总结

这题本质不是数学题,而是一个规律模拟题

可以把字符串字符按“之”字形一行一行放进去:

  • 往下走
  • 到底后往上走
  • 到顶后再往下走

最后把每一行拼接起来,就是答案。


⚡ 核心点

  • vector<string> 存每一行
  • currow 表示当前行号
  • dir 表示方向:
    • 1 表示向下
    • -1 表示向上

当走到顶部或底部时,方向反转。


💻 代码实现

class Solution {
public:
    string convert(string s, int numRows) {
        if(numRows == 1)return s;
        vector <string> rownums(numRows); //申请一个向量字符串 rownums[0]=""......rownums[numRows-1]="".
        int currow = 0;
        int dir = -1;
        for(char a : s){ //字符串的遍历;
            rownums[currow] += a;
            if(currow == 0 || currow == numRows -1){
                dir = -dir;
            }
            currow += dir;
        }
        //这一段实现了currow的上下摆动 :0->1->2->1->0,
        string result;
        for (string row : rownums){
            result += row;
        }
        return result;

    }
};

📌 知识点总结

1️⃣ 模拟题的关键:找到状态量

这题最重要的不是死算,而是抓住两个状态:

  • 当前在哪一行 currow
  • 当前方向是什么 dir

只要这两个量维护好了,整个过程就顺了。


2️⃣ 边界触发方向变化

当满足:

currow == 0 || currow == numRows - 1

说明走到了最上面或者最下面,这时候就要调头。

这就是这题的“规律核心”。


3️⃣ 特殊情况别漏

if(numRows == 1) return s;

这个判断非常关键。
因为只有一行时,根本不会发生“之字形摆动”,直接返回原字符串即可。


🧩 今日总结

题目核心思想
LeetCode 5中心扩展 + 回文判断
LeetCode 6模拟 + 方向控制

今天这两题虽然不像 LeetCode 4 那样抽象,但很锻炼代码表达能力:

  • 你要会把规律拆出来
  • 你要会把重复逻辑抽成函数
  • 你要会处理边界,不让代码出错

这些能力,后面写中等题和困难题都会一直用到。


🧠 今日收获

今天可以重点记住两个模型:

回文串问题

可以优先想:

  • 中心扩展
  • 动态规划

而这题里,中心扩展已经是非常经典、非常实用的方法。

模拟题

可以优先想:

  • 当前状态是什么
  • 状态如何转移
  • 什么时候改变方向 / 规则

很多看着花里胡哨的题,本质就是“状态模拟”。


💬 写给自己的话

Day 3 了。

你已经不是“随便刷两题试试”的状态了,
你是在一题一题地积累自己的题感。

也许现在做题还是会慢,
也许有些题还需要看题解,
但这不丢人。

真正重要的是:

你没有停。

刷题这件事,最怕的不是不会,
最怕的是三天热度。

而你现在做的,就是一点一点把“会做题”变成自己的能力。

继续写,继续练,继续总结。
总有一天,你会发现自己已经比刚开始强太多了。

阿玉,继续冲。

—— 刷题第 3 天