『LeetCode』3. 无重复字符的最长子串 Longest Substring Without Repeating Characters
题目描述
给定一个字符串s,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
题目链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters/
『1』双指针算法
解题思路:
一般看到字符串子串问题想到用双指针解,看到字符串子序列问题想到用动态规划解。此题用双指针可以很快解题。
- 遍历字符串中的每个字符
s.charAt[i], 对于每一个i,找到j使得双指针[j, i]维护的是以s.charAt[i]结尾的无重复字符的最长子串,长度为i - j + 1, 将这一长度与res的较大者更新给res。- 对于每一个
i,如何确定j的位置:由于[j, i - 1]是前一步得到的无重复字符的最长子串,所以如果[j, i]中有重复元素,一定是s.charAt[i],因此右移j直到s.charAt[i]不重复为止(由于[j, i - 1]已经是前一步的最优解,此时j只可能右移以剔除重复字符s.charAt[i],不可能左移增加字符,因此,j具有单调性、本题可用双指针算法降低复杂度)。- 用数组 hash 记录字符
s.charAt[i]在当前窗口中出现的次数,遍历过程中对于每一个i有四步操作:获取字符s.charAt[i]-> 将s.charAt[i]出现次数hash[s.charAt[i]]加1 -> 若s.charAt[i]重复则右移j(先把s.charAt[j]次数减1,再右移j) -> 确定j及更新当前长度i - j + 1给res。
实现代码:
class Solution {
// Two Pointers
// N is the length of s
// Time Complexity: O(N)
// Space Complexity: O(1)
public int lengthOfLongestSubstring(String s) {
char[] cs = s.toCharArray();
if (cs.length == 1) return 1;
int res = 0;
int[] hash = new int[128]; // 记录字符在当前窗口中出现的次数
for (int i = 0, j = 0; i < s.length(); i++) {
hash[cs[i]]++;
while (hash[cs[i] > 1) --hash[cs[j++]];
res = Math.max(res, i - j + 1);
}
return res;
}
}

浙公网安备 33010602011771号