【Day 1】拒绝温水煮青蛙,从今天开始公开打卡 | LeetCode 3. 无重复字符的最长子串 + Go map 基础用法

0 阅读3分钟

【Day 1】拒绝温水煮青蛙,从今天开始公开打卡 | LeetCode 3. 无重复字符的最长子串 + Go map 基础用法

  1. 今日打卡宣言 今天正式 Day 1!工作两年后明显感觉到技术停滞,项目忙+舒适区让我越来越没斗志。从今天起,用公开打卡逼自己每天进步一点,目标:连续100天不间断,年底前跳槽成功。欢迎大家监督我!

  2. LeetCode 部分(核心)

已解答

中等

相关标签

premium lock icon相关企业

提示

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 ****的长度。

 

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。注意 "bca""cab" 也是正确答案。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列, 不是子串。

 

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成
    • 难度:中等
    • 时间复杂度目标:O(n)
    • 核心思路(3行以内): 用滑动窗口 + map 记录字符最后出现的位置,右指针遍历,遇到重复就移动左指针到上一次出现位置的下一位。窗口大小不断更新最大值。
    • 代码(用 Go 写,面试常见):

Go

func lengthOfLongestSubstring(s string) int {
    if len(s) == 0 {
        return 0
    }
    charIndex := make(map[byte]int)  // 字符 -> 最后出现的位置
    maxLen, left := 0, 0

    for right := 0; right < len(s); right++ {
        if idx, ok := charIndex[s[right]]; ok && idx >= left {
            left = idx + 1  // 移动左边界
        }
        charIndex[s[right]] = right
        if right-left+1 > maxLen {
            maxLen = right - left + 1
        }
    }
    return maxLen
}

C++

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        // 核心思路, 滑动窗口加上map记录上一次相同字符的位置, 遇到相同的则left = idx + 1;
        if (s.empty())
        {
            return 0;
        }

        int maxLen = 0, left = 0;
        unordered_map<char, int> charIndex;

        for (int right = 0; right < s.size(); right ++)
        {
            if (charIndex.count(s[right]))
            {
                left = max(left, charIndex[s[right]] + 1);
            }
            charIndex[s[right]] = right;
            maxLen = max(maxLen, right - left + 1);
        }
        return maxLen;
    }
};
  • 易错点/优化点:

    1. 别用 charIndex[c] > left 判断,要 >= left(因为 left 刚好移动到重复位+1)
    2. map 用 byte 做 key 比 rune 更快(字符串是 byte 切片)
    3. 面试追问:如果要返回子串本身怎么改?(记录 maxStart + maxLen)
  1. 知识点部分(今天选 Go 基础,简单上手) Go map 的基础用法 & 常见面试点

    • 声明:m := make(map[keyType]valueType) 或 var m map[keyType]valueType(后者是 nil map,不能直接赋值)

    • 增删查:m[key] = val、delete(m, key)、val, ok := m[key]

    • 面试常问:

      • map 是线程安全的吗?(不是!并发读写 panic,用 sync.Map 或加锁)
      • 为什么 key 不能是 slice/func/map?(因为需要 hash,且 slice 等不可比较)
      • 今天题目中 map[byte]int 的优势:byte 是 uint8,hash 快,内存小。
  2. 今日感悟 其实这道题我以前刷过,但今天手写才发现自己对“左指针为什么移动到 idx+1”理解得不够透彻。公开打卡的好处就是:不敢水,必须搞懂再发。感觉第一步已经迈出去了,虽然小,但很踏实。

  3. 明天见!