3. 无重复字符的最长子串/面试题48. 最长不含重复字符的子字符串(简单) 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2: 输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3: 输入: “pwwkew” 输出: 3 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,”pwke” 是一个子序列,不是子串。
来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
思路1 动态规划思路
dp[j] 代表以字符 s[j] 为结尾的 “最长不重复子字符串” 的长度。
设字符 s[j] 左边距离最近的相同字符为 s[i] ,即 s[i] = s[j]。
当 i < 0 ,即 s[j]左边无相同字符,则 dp[j] = dp[j-1] + 1 ; 当 dp[j - 1] < j - i ,说明字符 s[i]在子字符串 dp[j-1]区间之外 ,则 dp[j] = dp[j - 1] + 1 ; 当 dp[j−1]≥j−i ,说明字符 s[i]s[i] 在子字符串 dp[j-1]区间之中 ,则dp[j] 的左边界由 s[i] 决定,即 dp[j] = j - i; $$ d p[j]=\left{\begin{array}{ll} d p[j-1]+1 & , d p[j-1]<j-i \ j-i & , d p[j-1] \geq j-i \end{array}\right. $$
思路2 滑动窗口,实质性也是动态规划,未写
代码1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution { public int lengthOfLongestSubstring (String s) { int res = 0 ,max = 0 ; for (int i=0 ;i<s.length();i++){ int k =i-1 ; while (k>=0 && s.charAt(k)!=s.charAt(i)) k--; res = res<i-k?res+1 :i-k; max = Math.max(res,max); } return max; } }
代码2:(用这个) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Solution { public int lengthOfLongestSubstring (String s) { int [] last = new int [128 ]; for (int i = 0 ; i < 128 ; i++) { last[i] = -1 ; } int len = s.length(); int res =0 ; int start =0 ; for (int i=0 ;i<len;i++){ int c = s.charAt(i); start = Math.max(start,last[c]+1 ); res = Math.max(res,i-start+1 ); last[c]=i; } return res; } }
代码2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class Solution { public int lengthOfLongestSubstring (String s) { HashMap<Character, Integer> window = new HashMap<>(); int left =0 ,right=0 ; int res = 0 ; while (right<s.length()){ char c = s.charAt(right); right++; window.put(c,window.getOrDefault(c,0 )+1 ); while (window.get(c)>1 ){ char c1 = s.charAt(left); left++; window.put(c1,window.getOrDefault(c1,0 )-1 ); } res = Math.max(res,right-left); } return res; } }