【DP】剑指 Offer 48. 最长不含重复字符的子字符串
题目:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
解答:
DP
状态定义:dp[j]表示以s.charAt(j)为结尾的子字符串的“的字符串”的长度
转移方程: 固定右边界 j,设字符 s[j]左边距离最近的相同字符为s[i] ,即s[i] == s[j]
获得s[i]的方法有多种:
1,用哈希表,用此法,时间复杂度为o(n)
2,线性遍历,往s[j]左边找第一个相同的字符即可,用此法,时间复杂度为o(n^2)
dp[j] = dp[j-1] + 1(dp[j-1]<j-i)
dp[i] = j-i (dp[j-1]>=j-i)
代码:
class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); if(n == 0){ return 0; } int[] dp = new int[n]; dp[0] = 1; Map<Character,Integer> map = new HashMap<>(); map.put(s.charAt(0),0); int res = dp[0]; for(int j = 1;j<n;j++){ int i = map.getOrDefault(s.charAt(j),-1); map.put(s.charAt(j),j); if(dp[j-1]<j-i){ dp[j] = dp[j-1]+1; }else{ dp[j] = j-i; } res = Math.max(dp[j],res); } return res; } }
代码优化:
优化空间复杂度
class Solution { public int lengthOfLongestSubstring(String s) { int n = s.length(); if(n == 0){ return 0; } //int[] dp = new int[n]; int pre = 1,p; Map<Character,Integer> map = new HashMap<>(); map.put(s.charAt(0),0); int res = 1; for(int j = 1;j<n;j++){ int i = map.getOrDefault(s.charAt(j),-1); map.put(s.charAt(j),j); if(pre<j-i){ p = pre+1; }else{ p = j-i; } pre = p; res = Math.max(p,res); } return res; } }
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: "abcabcbb"输出: 3 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。示例 2:
输入: "bbbbb"输出: 1解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。示例 3:
输入: "pwwkew"输出: 3解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/zui-chang-bu-han-zhong-fu-zi-fu-de-zi-zi-fu-chuan-lcof著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

浙公网安备 33010602011771号