每日一题 - 剑指 Offer 48. 最长不含重复字符的子字符串
题目信息
时间: 2019-07-02
题目链接:Leetcode
tag: 动态规划 哈希表
难易程度:中等
题目描述:
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
注意
1. s.length <= 40000
解题思路
本题难点
长度为 N 的字符串共有 (1+N)N/2 个子字符串(复杂度为 O(N^2 ) ),判断长度为 N 的字符串是否有重复字符的复杂度为 O(N) ,使用暴力法解决的复杂度为 O(N^3) 。
具体思路
考虑使用动态规划降低时间复杂度。
- 状态定义:设动态规划列表 dp ,dp[j] 代表以字符 s[j 为结尾的 “最长不重复子字符串” 的长度。
- 转移方程:固定右边界 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] 在子字符串 dp[j−1] 区间之中 ,则 dp[j] 的左边界由 s[i] 决定,即 dp[j]=j−i ;
注意:当 i<0 时,由于 dp[j−1]≤j 恒成立,因而 dp[j−1]<j−i 恒成立,因此分支 1. 和 2. 可被合并。

代码
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character, Integer> dic = new HashMap<>();
int res = 0, tmp = 0;
for(int j = 0; j < s.length(); j++) {
int i = dic.getOrDefault(s.charAt(j), -1); // 获取索引 i
dic.put(s.charAt(j), j); // 更新哈希表
tmp = tmp < j - i ? tmp + 1 : j - i; // dp[j - 1] -> dp[j]
res = Math.max(res, tmp); // max(dp[j - 1], dp[j])
}
return res;
}
}
复杂度分析:
- 时间复杂度 O(N) :其中 N为字符串长度,动态规划需遍历计算 dp列表。
- 空间复杂度 O(1) : 字符的 ASCII 码范围为 0 ~ 127 ,哈希表 dic 最多使用 O(128)=O(1) 大小的额外空间。
其他优秀解答
解题思路
双指针 + 哈希表
哈希表 dic统计: 指针 j遍历字符 s,哈希表统计字符 s[j]最后一次出现的索引 。
更新左指针 i : 根据上轮左指针 i 和 dic[s[j]] ,每轮更新左边界 i ,保证区间 [i+1,j] 内无重复字符且最大
更新结果 res : 取上轮 res 和本轮双指针区间 [i+1,j] 的宽度(即 j−i )中的最大值。
代码
class Solution {
public int lengthOfLongestSubstring(String s) {
Map<Character,Integer> dic = new HashMap<>();
int i = -1,res = 0;
//遍历字符串 s
for(int j = 0; j < s.length();j++){
//遍历到 s[j] 时,可通过访问哈希表 dic[s[j]] 获取最近的相同字符的索引 i
if(dic.containsKey(s.charAt(j))){
//取最大值因为防止abba的情况出现
i = Math.max(i,dic.get(s.charAt(j)));
}
//使用哈希表统计 各字符最后一次出现的索引位置
dic.put(s.charAt(j),j);
res = Math.max(res,j-i);
}
return res;
}
}
每日一题 - 剑指 Offer 48. 最长不含重复字符的子字符串的更多相关文章
- 剑指 Offer 48. 最长不含重复字符的子字符串 + 动态规划 + 哈希表 + 双指针 + 滑动窗口
剑指 Offer 48. 最长不含重复字符的子字符串 Offer_48 题目详情 解法分析 解法一:动态规划+哈希表 package com.walegarrett.offer; /** * @Aut ...
- 【Java】 剑指offer(48) 最长不含重复字符的子字符串
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字 ...
- 剑指 Offer 48. 最长不含重复字符的子字符串
题目描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度. 示例1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 & ...
- 剑指offer——50最长不含重复字符和子字符串
题目: 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度.假设字符串中只包含’a~z”的字符.例如,在字符串“arabcacfr"中,最长的不含重复字符的子字符串 ...
- 剑指offer-面试题48-最长不含重复字符的子字符串-动态规划
/* 题目: 最长不含重复字符的子字符串. */ /* 思路: f(i) = f(i-1) + 1,(未出现过当前字符,distance > f(i-1) distance,当前字符和上一次出现 ...
- 剑指offer面试题48: 最长不含重复字符的子字符串
Given a string, find the length of the longest substring without repeating characters.(请从子字符串中找出一个最长 ...
- 《剑指offer》面试题48. 最长不含重复字符的子字符串
问题描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串 ...
- 《剑指offer》第四十八题(最长不含重复字符的子字符串)
// 面试题48:最长不含重复字符的子字符串 // 题目:请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子 // 字符串的长度.假设字符串中只包含从'a'到'z'的字符. #inclu ...
- 【Offer】[48] 【最长不含重复字符的子字符串】
题目描述 思路分析 测试用例 Java代码 代码链接 题目描述 请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度.假设字符串中只包含'a'~'z'的字符.例如,在字符串&q ...
随机推荐
- Java实现 蓝桥杯 算法提高 奥运会开幕式
试题 算法提高 奥运会开幕式 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 学校给高一(三)班分配了一个名额,去参加奥运会的开幕式.每个人都争着要去,可是名额只有一个,怎么办?班长 ...
- 看Python如何无缝转换Word和Excel
word和excel是办公过程必不可少的两个文档类型,word多用于文字处理,比如备忘录.论文.书籍.报告.商业信函等,excel可以制作精美的图表,还可以计算.分析.记录数据.二者在功能达成上有重叠 ...
- 09 . Nginx配置LNMP和LNMT架构
安装LNMP架构 环境清单 list CentOS7.3 proxysql-2.0.12-1-centos7.x86_64.rpm mysql-5.7.23-1.el7.x86_64.rpm-bund ...
- 深入浅出-iOS Block原理和内存中位置
Posted by 微博@Yangsc_o 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 #简介 今天回顾一下blcok,基本 ...
- struts用action的属性接收参数
新建一个javaweb项目 在项目中加入Struts.xml( 选中项目右键MyEclipse-->project facets-->Struts2-->finish) 在src项目 ...
- @atcoder - AGC034F@ RNG and XOR
目录 @description@ @solution@ @accepted code@ @details@ @description@ 给定一个值域在 [0, 2^N) 的随机数生成器,给定参数 A[ ...
- 一文读懂 Java 异常体系
写程序的时候,编辑器会提示错误,关键字拼错了,语法不符合规则,不符合泛型:程序编译的时候,编译器会提示错误,检查是否符合 Java 的语法规范,没有通过编译器检查的程序就无法编译,也就无法运行.这些都 ...
- LR脚本信息函数-lr_whoami
void lr_whoami(int * vuser_id,char ** sgroup,int * scid); 参数说明: vuser_id:指向用于存储Vuser ID号的输出参数的指针. sg ...
- 深度解密 Go 语言之 sync.map
工作中,经常会碰到并发读写 map 而造成 panic 的情况,为什么在并发读写的时候,会 panic 呢?因为在并发读写的情况下,map 里的数据会被写乱,之后就是 Garbage in, garb ...
- numpy中的浅复制和深复制
浅复制:主要有两种方式,简单的赋值或者使用视图(view) 简单的赋值:其实就是制造了一个别名,数组并没有被copy成新的一份,当使用其中一个别名改变数组值的时候,另一个别名对应的值一并改变. > ...