1. 程式人生 > >劍指Offer-題48(Java版):最長不含重複字元的子字串

劍指Offer-題48(Java版):最長不含重複字元的子字串

參考自:《劍指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; } }