劍指Offer-題48(Java版):最長不含重複字元的子字串
阿新 • • 發佈:2019-02-18
參考自:《劍指Offer——名企面試官精講典型程式設計題》
題目:最長不含重複字元的子字串
請從字串中找出一個最長的不包含重複字元的子字串,計算該最長子字串的長度。假設字串中只包含從’a’到’z’的字元。例如,在字串中”arabcacfr”,最長非重複子字串為”acfr”,長度為4。
主要思路:使用動態規劃,記錄當前字元之前的最長非重複子字串長度f(i-1),其中i為當前字元的位置。每次遍歷當前字元時,分兩種情況:
1)若當前字元第一次出現,則最長非重複子字串長度f(i) = f(i-1)+1。
2)若當前字元不是第一次出現,則首先計算當前字元與它上次出現位置之間的距離d。若d大於f(i-1),即說明前一個非重複子字串中沒有包含當前字元,則可以添加當前字元到前一個非重複子字串中,所以,f(i) = f(i-1)+1。若d小於或等於f(i-1),即說明前一個非重複子字串中已經包含當前字元,則不可以添加當前字元,所以,f(i) = d。
關鍵點:動態規劃,兩個重複字元的距離
時間複雜度:O(n)
public class LongestSingleSubstring
{
public static void main(String[] args)
{
System.out.println(findLongestSubstringLength("arabcacfr")); //4
System.out.println(findLongestSubstringLength("bbb")); //1
System.out.println(findLongestSubstringLength("" )); //0
}
private static int findLongestSubstringLength(String string)
{
if (string == null || string.equals("")) return 0;
int maxLength = 0;
int curLength = 0;
int[] positions = new int[26];
for (int i = 0; i < positions.length; i++)
{
positions[i] = -1 ; //初始化為-1,負數表示沒出現過
}
for (int i = 0; i < string.length(); i++)
{
int curChar = string.charAt(i) - 'a';
int prePosition = positions[curChar];
//當前字元與它上次出現位置之間的距離
int distance = i - prePosition;
//當前字元第一次出現,或者前一個非重複子字串中沒有包含當前字元
if (prePosition < 0 || distance > curLength)
{
curLength++;
} else
{
//更新最長非重複子字串的長度
if (curLength > maxLength)
{
maxLength = curLength;
}
curLength = distance;
}
positions[curChar] = i; //更新字元出現的位置
}
if (curLength > maxLength)
{
maxLength = curLength;
}
return maxLength;
}
}