給定一個字符串,請你找出其中不含有重複字符的 最長子串 的長度。
示例 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;
}