Leetcode:Longest Substring Without Repeating Characters分析和实现
题目大意是传入一条字符串,计算出这样的这样一条子字符串,要求子字符串是原字符串的连续的某一段,且子字符串内不包含两个或两个以上的重复字符。求符合上面条件的字符串中最长的那一条的长度。
首先注意到任意一条无重复子字符串的任意子字符串应该也满足无重复这一特性。因此这个问题可以用动态规划解决。
需要先计算出字符串s的每个元素对应的首个重复字符的下标,字符串中下标为i的元素的首个重复字符的下标j应该满足j > i && s[i] == s[j],且是满足这些条件中的最小值。比如asaa中下标为0的元素对应的首个重复字符的下标为2,尽管3也满足条件,但不是最小值。
计算的方式如下:
registries = int[256]
nextOccurance = int[s.length]
initialize elements in registries with -1 //将所有registries 中的元素都初始化为-1
initialize elements in nextOccurance with s.length //将所有registries 中的元素都初始化为s.length
for(i = 0; i < s.length; i++)
c = s[i]
if registries[c] != -1 then
nextOccurance [registries[c]] = i
registries[c] = i
这里用注册表registries的注册项registries[c]记录当前对字符c的查找请求,而nextOccurance的元素nextOccurance[i]表示s[i]的首个重复字符子s中的下标。每次循环时,都会检测注册表项registries[c]是否以及被注册,如果注册则为nextOccurance [registries[c]]记录当前下标i。最后则将之前的注册项清除,而用当前下标作为新的请求项。
之后使用动态规划解决问题。利用数组longestLengthes,longestLengthes[i]表示所有以下标i作为起始的无重复子字符串的最长长度。显然longestLengthes[s.length - 1]应该为1。而对于任意i < s.length - 1,应该有longestLengthes[i] = min(longestLengthes[i + 1] + 1, nextOccurance [i] - i)。其中longestLengthes[i + 1] + 1表示理想状态下(不考虑出现多个longestLengthes[i]对应的字符)的最优长度,而nextOccurance [i] - i表示可能的以下标i作为起始的无重复子字符串的最长长度,因为s[i] == s[nextOccurance [i]],这里已经发生了重复。之所以敢保证longestLengthes[i] <= longestLengthes[i + 1] + 1是因为假如longestLengthes[i]>longestLengthes[i + 1] + 1,那么显然longestLengthes[i + 1] >= longestLengthes[i] - 1 >longestLengthes[i + 1](整体不重复自然局部不会重复),这是不可能发生的。(如果对这部分不理解,可以枚举可能的情况,总共只有三种)转换成代码:
longestLengthes = int[s.length]
longestLengthes[s.length - 1] = 1
for(i = s.length - 2; i >= 0; i--)
longestLengthes[i] = min(longestLengthes[i + 1] + 1, nextOccurance [i] - i)
之后遍历整个longestLengthes数组就可以找到最长的无重复子字符串的长度。
把上面两部分的代码整合,可以轻易得出整体的复杂度为O(n),其中n为传入字符串的长度。
最后给出整个实现代码,给有需要的人:
package cn.dalt.leetcode;
/**
* Created by Administrator on 2017/6/4.
*/
public class LongestSubstringWithoutRepeatingCharacters {
public static void main(String[] args) {
String s = "yiwgczzovxdrrgeebkqliobitcjgqxeqhbxkcyaxvdqplxtmhmarcbzwekewkknrnmdpmfohlfyweujlgjf";
System.out.println(new LongestSubstringWithoutRepeatingCharacters().lengthOfLongestSubstring(s));
for(char c = 0; c < 256; c++)
{
System.out.println((int)c + ":" + c);
}
}
int[] nextOccurIndexes = null;
int[] registries = new int[1 << 8];
public int lengthOfLongestSubstring(String s) {
//Calculate all next occur indexes
//nextOccurIndexes[i] is the minimun index of s which has properties that index > i && s[i] = s[index]
int slength = s.length();
if (slength == 0) {
return 0;
}
nextOccurIndexes = new int[s.length()];
for (int i = 0, bound = registries.length; i < bound; i++) {
registries[i] = -1;
}
for (int i = 0, bound = s.length(); i < bound; i++) {
int c = s.charAt(i);
int registry = registries[c];
if (registry != -1) {
nextOccurIndexes[registry] = i;
}
registries[c] = i;
}
for (int registry : registries) {
if (registry != -1) {
nextOccurIndexes[registry] = slength;
}
}
int[] longestNoneRepetitionSubstringLengthes = new int[s.length()];
longestNoneRepetitionSubstringLengthes[s.length() - 1] = 1;
int longestNoneRepetitionSubstringIndex = s.length() - 1;
for (int i = s.length() - 2; i >= 0; i--) {
int probablyMaxLength1 = longestNoneRepetitionSubstringLengthes[i + 1] + 1;
int probablyMaxLength2 = nextOccurIndexes[i] - i;
longestNoneRepetitionSubstringLengthes[i] = Math.min(probablyMaxLength1, probablyMaxLength2);
longestNoneRepetitionSubstringIndex =
longestNoneRepetitionSubstringLengthes[i] > longestNoneRepetitionSubstringLengthes[longestNoneRepetitionSubstringIndex] ?
i : longestNoneRepetitionSubstringIndex;
}
return longestNoneRepetitionSubstringLengthes[longestNoneRepetitionSubstringIndex];
}
}
Leetcode:Longest Substring Without Repeating Characters分析和实现的更多相关文章
- [LeetCode] Longest Substring Without Repeating Characters 最长无重复子串
Given a string, find the length of the longest substring without repeating characters. For example, ...
- leetcode: longest substring without repeating characters
July 16, 2015 Problem statement: Longest Substring Without Repeating Characters Read the blog: http: ...
- LeetCode:Longest Substring Without Repeating Characters(最长不重复子串)
题目链接 Given a string, find the length of the longest substring without repeating characters. For exam ...
- [LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串
Given a string, find the length of the longest substring without repeating characters. Example 1: In ...
- C++ leetcode Longest Substring Without Repeating Characters
要开学了,不开森.键盘声音有点大,担心会吵到舍友.今年要当个可爱的技术宅呀~ 题目:Given a string, find the length of the longest substring w ...
- [LeetCode]Longest Substring Without Repeating Characters题解
Longest Substring Without Repeating Characters: Given a string, find the length of the longest subst ...
- [LeetCode] Longest Substring Without Repeating Characters 最长无重复字符的子串 C++实现java实现
最长无重复字符的子串 Given a string, find the length of the longest substring without repeating characters. Ex ...
- LeetCode——Longest Substring Without Repeating Characters
Given a string, find the length of the longest substring without repeating characters. For example, ...
- [Leetcode] Longest Substring Without Repeating Characters (C++)
题目: Given a string, find the length of the longest substring without repeating characters. For examp ...
随机推荐
- 无法打开包括文件:“iostream.h”
把#include<iostream.h>改为:#include<iostream>using namespace std; #include<iostream.h> ...
- 压缩感知Compressive sensing(一)
compressive sensing(CS) 又称 compressived sensing ,compressived sample,大意是在采集信号的时候(模拟到数字),同时完成对信号压缩之意. ...
- 智能电视软件安装(WIFI上网)
智能电视软件上网(电视可连接无线网的称之为:智能电视) 1.安装当贝市场 链接:http://www.dangbei.com/ 2.安装电视家浏览器 链接:http://www.tvapk.net/f ...
- WCF *.svc 自定义地址路由映射
一般在创建WCF服务时会用Serivce.svc文件访问,地址如:http://localhost/applicationname/Serivce.svc/Name 现在用路由映射成:http://l ...
- openfaas cli 安装
1. 安装脚本 curl -sL https://cli.get-faas.com/ | sudo sh 备注安装完成之后如果没有 faas-cli 可以下载脚本,手工执行 2. 使用二进制 ...
- bzoj 2119 股市的预测 —— 枚举关键点+后缀数组
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2119 思路就是对于这个形如 ABA 的串,枚举 A 的长度,并按照长度分出几块,找到一些关键 ...
- jmeter --- 测试计划里的元件
1.线程组 线程组元件是任何一个测试计划的开始点.在一个测试计划中的所有元件都必须在某个线程组下.顾名思义,线程组元件控制JMeter执行你的测试计划时候使用的线程数量.对线程组的控制允许你: 设置线 ...
- 在window下 进入系统盘命令
示例: cd C:\work 查看文件夹直接在当前路径下输入 dir 在当前路径下输入 dir/? 查看帮助
- 让Eclipse的TomcatPlugin支持Tomcat 8.x
使用tomcat插件启动项目的优势: 1.TomcatPlugin是一个免重启的开发插件,原始的Servers方式启动tomcat项目,修改xxx.ftl 或者 xxx.jsp 文件后需要重启to ...
- linux下用户和组相关的文件及相关管理命令
1.用户信息文件 /etc/passwd 示例root:x:0:0:root:/root:/bin/bashbin:x:1:1:bin:/bin:/sbin/nologindaemon:x:2:2: ...