大家都知道,手写算法题是大厂面试的必考环节,俗称“压轴题”。 这就像游戏里打怪升级,遇到的第一个大BOSS——
蓝色大头幽魂上线!不打过它,通关别想。。

黑神话:悟空 大头怪
让我们来分析一下,为什么这个“幽魂BOSS(数据结构与算法)”如此难打?
明知道刷题很重要,却总是迟迟不动手; 哪怕一次次在面试里栽跟头,转身也没多少改变; 是不是我太懒了?
★真相可能不是“懒”,而是想得太多:
于是我们的大脑自我保护,
悄悄切换成“拖延模式”:“今天太累了,明天再战。”
一说“刷题”,很多人脑子里立马闪过 “LeetCode”
一看题量就懵了:1千多道题,一个题做一周,刷完得 19 年……
好家伙,还没开始面试,人已经先缴械投降了。
干脆放弃,去摆个小摊,卖煎饼可能都比这快。
经验丰富的刷题党普遍认为:
★稳定掌握 LeetCode 前 150 题,能够总结出自己的解题思路和套路,才是高效准备 BAT 等大厂面试的关键。
稍微有心从网络搜索以下,不少刷过1千题人总结 刷题路线,面试经典高频 150 题,让新手避免很多坑,甚至组建付费刷题小分队。解决大部分人问题
完整地址:https://docs.qq.com/sheet/DY1NwcGZjUXpYb01j?tab=oqi27u


不少人分享过: 自己只刷了 50~60 题,就成功拿到了大厂 offer。
秘诀其实就两个字:重复!
一个题刷三遍,也能刷出“150题”的水准。

★有没有可能,眼前那密密麻麻的 1000 道题,突然都消失了,只剩下一道? 你专心把这一道题反复练,练到极致:
这才是真正的成长路线。 刷题,不是比谁刷得多,而是比谁刷得深、刷得熟。 别总幻想“下周就能“高屋建瓴吊打面试官”,
就像“八段锦”这套功法,全套只有八个动作。 刷题也一样。 与其每天换新题、贪多求快,不如挑出经典题,反复刷、认真练。
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。示例 1:
输入: s = "abcabcbb"输出: 3解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 3:输入: s = "pwwkew"输出: 3解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个_子序列,_不是子串

提示:
0 <= s.length <= 5 * 104s 由英文字母、数字、符号和空格组成分析:


0ms击败100.00
int lengthOfLongestSubstring(char* s)
{
//定义数据结构
int hashMap[128]; //key 字符 value 字符对应的下标 定义不是 char hashMap[128];
//为什么是128 ASCII 字符集标准中定义了 128 个字符,对应编号 0 ~ 127
memset(hashMap,-1,sizeof(hashMap));
//unsigned char 是唯一可以无损表示、访问任意类型对象的内存的类型。
//According to the C and C++ standards
//The object representation of an object is the sequence of unsigned char stored in memory
//https://en.cppreference.com/w/cpp/string/byte/memset
char* startPtr = s; // 窗口起点指针
int startIndex = 0; // 记录窗口起点的索引
char* endPtr = s; // 窗口终点指针,因为指针结构 不清楚当前字符串的长度。
int maxLen = 0;// 保存最大长度
char tempChar;
//在C语言设计之初,计算机的内存资源非常有限。
// 为了最大限度地节省内存,C语言选择了使用一个单一的字节('\0')来标记字符串结束,
// 而不是像一些其他语言那样记录字符串的长度。如果采用记录长度的方式,
// 可能需要额外的几个字节来存储长度信息
//数组像制作一样使用。这里为体现c语言特性 故意没有
while(*endPtr != '\0')
{
tempChar= *endPtr; //字符--位置
//重复,原来重复字符串不符合要求
if(hashMap[tempChar] != -1 && hashMap[tempChar] >= (startPtr -s )){
// char* s = "hello";
// char* start = s + 2; // 指向字符 'l',即索引为2的位置
// int offset = start - s; // offset == 2
startPtr = s + hashMap[tempChar] + 1; // 指针跳转
}
// 更新字符最新出现位置
hashMap[tempChar] = (int)(endPtr - s); //指针可以之间相减
int curLen = (int)(endPtr - startPtr) + 1;
if (curLen > maxLen) {
maxLen = curLen;
}
endPtr++;
}
return maxLen;
}
优点 | 说明 |
|---|---|
✅ 指针操作高效 | 不使用数组索引,完全用指针运算,贴近底层,效率高 |
✅ ASCII字符支持完整 | 使用大小为128的数组支持全部可打印和控制字符(含空格、制表符等) |
✅ 无需额外库 | 无需引入哈希表、链表等复杂结构,代码简洁、纯 C 实现 |
✅ 逻辑清晰易于维护 | 使用 -1 表示“字符未出现”,避免使用偏移量+1等技巧,判断更直观 |
✅ 最优时间复杂度 | 滑动窗口双指针做到了 O(n),适合大多数面试/竞赛/实际场景 |
✅ 可扩展性好 | 稍作修改即可支持更多字符集(如 Unicode、UTF-8) |
指针操作 vs 数组索引:本质是一样的
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int ret =0;
int begin =0; //开始位置
int end =0;
vector<int> hash(128,-1); //hash[s[i]]=i;
for(end =0;end<s.size();end++)
{
char temp =s[end];
if(hash[temp]!=-1 && hash[temp] >=begin)
{
begin=hash[temp]+1;
}
ret =max(ret,end-begin+1);
hash[temp]=end;
}
return ret;
}
};
func lengthOfLongestSubstring(s string) int {
//定义数据结构
const asciiSize = 128
hashMap := [asciiSize]int{}
for i := range hashMap {
hashMap[i] = -1
}
start, maxLen := 0, 0
// 实现算法
for i, ch := range s {
if hashMap[ch] >= start {
start = hashMap[ch] + 1
}
hashMap[ch] = i
maxLen = max(maxLen, i - start + 1)
}
return maxLen
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
use std::collections::HashMap;
impl Solution {
pub fn length_of_longest_substring(s: String) -> i32 {
let mut map = HashMap::new(); // 存字符 -> 最新索引
let (mut start, mut max_len) = (0usize, 0usize);
for (i, c) in s.chars().enumerate() {
//Rust 的模式匹配写法,用来**判断
//HashMap 中是否有键 `c` 的值**,并把值绑定给 `prev_index`。
if let Some(&prev_index) = map.get(&c) {
if prev_index >= start {
start = prev_index + 1;
}
}
map.insert(c, i);
max_len = max_len.max(i - start + 1);
//`.max()` 方法是 Rust 标准库 `Ord` trait 自带的
}
max_len as i32 //返回 `i32`
}
}
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
char_index = {} //用大括号 `{}` 创建空字典
start = 0
max_len = 0
//`enumerate` 是 Python 内置函数,
//常用来在遍历序列(如列表、字符串)时,同时获得元素的索引和值
for i, c in enumerate(s):
//有重复元素
if c in char_index and char_index[c] >= start:
start = char_index[c] + 1
char_index[c] = i
max_len = max(max_len, i - start + 1)
return max_len
