PHP 8.0 推荐用滑动窗口+哈希表求最长无重复字符子串,时间复杂度O(n),核心是双指针与max($left, $map[$char]+1)防左指针回退,返回子串。

要找出字符串中最长的无重复字符子串,PHP 8.0 推荐使用「滑动窗口 + 哈希表记录位置」方法,时间复杂度 O(n),空间复杂度 O(min(m,n))(m 为字符集大小),比暴力遍历高效得多。
核心思路:用双指针维护有效窗口
定义左指针 $left 和右指针 $right,初始都为 0。右指针不断右移扩展子串,同时用关联数组记录每个字符最后出现的索引。一旦遇到重复字符(即当前字符已存在且其位置 ≥ $left),就把 $left 移到该字符上次出现位置的下一位,保证窗口内无重复。
关键细节:如何更新左边界才不回退
左指针不能简单设为 $map[$char] + 1,必须取最大值避免误缩:
- 如果重复字符上次出现在窗口外(比如之前被跳过),$left 不应后退
- 正确写法:$left = max($left, $map[$char] + 1);
- 例如:"abba" 中处理第二个 'a' 时,$map['a'] 是 0,但此时 $left 已到 2(因 'b' 重复),所以不能退回
PHP 8.0 实现要点(兼容严格模式)
利用 PHP 8.0 的联合类型和 nullsafe 操作可增强健壮性,但本题核心无需复杂类型声明。注意以下几点:
- 字符串用 str_split($s) 或直接 $s[$i] 访问(PHP 8 支持对字符串下标访问返回 string)
- 初始化 $map = [];,键为字符,值为最新索引
- 每次循环更新最大长度:$maxLen = max($maxLen, $right - $left + 1);
- 返回的是长度还是子串?题目说“找出”,建议返回子串(如需长度,改 return $maxLen 即可)
完整可运行代码(PHP 8.0+)
function lengthOfLongestSubstring(string $s): string
{
$n = strlen($s);
if ($n === 0) return '';
<pre class="brush:php;toolbar:false;">$map = [];
$left = 0;
$maxStart = 0;
$maxLen = 0;
for ($right = 0; $right = $left) {
$left = $map[$char] + 1;
}
$map[$char] = $right;
$currentLen = $right - $left + 1;
if ($currentLen > $maxLen) {
$maxLen = $currentLen;
$maxStart = $left;
}
}
return substr($s, $maxStart, $maxLen);}
// 测试 var_dump(lengthOfLongestSubstring("abcabcbb")); // "abc" var_dump(lengthOfLongestSubstring("bbbbb")); // "b" var_dump(lengthOfLongestSubstring("pwwkew")); // "wke" 或 "kew"(任一最长即可)
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











