给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
using System;
using System.Collections.Generic;
namespace 无重复字符的最长子串
{
class Program
{
static void Main(string[] args)
{
while (true)
{
int length = 0;
string s = Console.ReadLine();
length = LengthOfLongestSubstring(s);
Console.WriteLine(length);
}
}
//使用Dictionary记录当前字符和它的位置,每次向dic中添加新项时,先判断dic中有没有重复的值
//如果要添加的项在原dic中存在,记录当前的dic长度并将i移至原字符串重复字符的下一个字符处,重新遍历。
//这种方法在字符串全都是重复字符时(如:“aaaaaaaaa”)相当于是两个for循环,耗时较长,但是Dictionary
//键值对集合如果存储键值相同的元素时会报错,而且通过值获取键的方式很麻烦,java中有更好的方法
public static int LengthOfLongestSubstring(string s)
{
if (s.Length <= 0)
{
return 0;
}
char[] c = s.ToCharArray();
Dictionary<char, int> dic = new Dictionary<char, int>();
int length = 1;
int max = 1;
int i = 0;
int j = 0;
for(i = 0; i < c.Length; i++)
{
if (!dic.ContainsKey(c[i]))
{
dic.Add(c[i], i);
if (length > max)
{
max = length;
}
length++;
}
else
{
length = 1;
i = dic[c[i]];
dic.Clear();
}
}
return max;
}
}
}
优化后的java代码
public int lengthOfLongestSubstring(String s) {
int n = s.length(), ans = 0;
Map<Character, Integer> map = new HashMap<>(); // current index of character
// try to extend the range [i, j]
for (int j = 0, i = 0; j < n; j++) {
if (map.containsKey(s.charAt(j))) {
i = Math.max(map.get(s.charAt(j)), i);
}
ans = Math.max(ans, j - i + 1);
map.put(s.charAt(j), j + 1);
}
return ans;
}