难度:中等
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

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

提示:

s.length <= 40000

方法一:双指针+Map(哈希表)

剑指 Offer 48. 最长不含重复字符的子字符串 - 图1

  1. /**
  2. * @param {string} s
  3. * @return {number}
  4. */
  5. // 双指针+Map(哈希表)
  6. var lengthOfLongestSubstring = function(s) {
  7. let i = -1 ;
  8. let res = 0;
  9. let hashMap = new Map()
  10. for(let j=0;j<s.length;j++){
  11. if(hashMap.has(s.charAt(j))){
  12. i = Math.max(i,hashMap.get(s.charAt(j)))
  13. }
  14. hashMap.set(s.charAt(j),j)
  15. res = Math.max(res,j-i)
  16. }
  17. return res
  18. };

方法二:动态规划 + 哈希表

c425fe7767a4f240b4653563be52d45.png

  1. /**
  2. * @param {string} s
  3. * @return {number}
  4. */
  5. var lengthOfLongestSubstring = function(s) {
  6. let tmp = 0;
  7. let res = 0;
  8. let hashMap = new Map()
  9. for(let i = -1, j= 0;j<s.length;j++){
  10. if(hashMap.has(s.charAt(j))){
  11. i = Math.max(i,hashMap.get(s.charAt(j)))
  12. }
  13. hashMap.set(s.charAt(j),j)
  14. tmp = tmp<j-i?tmp+1:j-i // dp[j - 1] -> dp[j]
  15. res = Math.max(res,tmp) // max(dp[j - 1], dp[j])
  16. }
  17. return res
  18. };

方法三:动态规划+线性遍历

a31425e0d3e5d9b56a9ae9e93265a0c.png

  1. /**
  2. * @param {string} s
  3. * @return {number}
  4. */
  5. //动态规划+线性遍历
  6. var lengthOfLongestSubstring = function(s) {
  7. let tmp = 0;
  8. let res = 0;
  9. for(let j = 0;j<s.length;j++){
  10. let i= j-1;
  11. while(i>=0&&s.charAt(i)!=s.charAt(j))i--
  12. tmp = tmp<j-i?tmp+1:j-i // dp[j - 1] -> dp[j]
  13. res = Math.max(res,tmp) // max(dp[j - 1], dp[j])
  14. }
  15. return res
  16. };