【劍指offer】最長不含重復字符的子字符串


題目:

* 面試題48:請從字符串中找出一個最長的不包含重復字符的子字符串,
* 計算該最長子字符串的長度。假設字符串中只包含從'a'到'z'的字符。
* 例如,在字符串中'arabcacfr',最長非重復子字符串為'acfr',長度為4。

思路:

(1)暴力枚舉所有子字符串,一個個檢測是否重復

(2)動態規划:設字符串為string

  設dp(i) 表示以 string(i) 結尾的 並且不包含重復字符的子字符串  的最大長度

  dp(i) = dp(i-1) + 1, 當 string[ i ] 沒有在 dp[ i-1 ]表示的字符串出現過 

  dp(i) = i -  lastAppear  當 string[ i ] 在 dp[ i-1 ]表示的字符串出現過,記其下標為 lastAppear

代碼:

 1 package aim_to_offer_second_edition.ch5;
 2 
 3 /***
 4  * 面試題48:請從字符串中找出一個最長的不包含重復字符的子字符串,
 5  * 計算該最長子字符串的長度。假設字符串中只包含從'a'到'z'的字符。
 6  * 例如,在字符串中'arabcacfr',最長非重復子字符串為'acfr',長度為4。
 7  * @author Saber
 8  * 思路:
 9  * (1)暴力枚舉
10  * (2)動態規划:
11  *         設dp[i] 表示以s[i]結尾並且不包含重復字符,的子字符串最大長度
12  *         dp[i] = {
13  *                    dp[i-1] + 1, 當s[i-dp[i-1], i-1]中不存在s[i]
14  *                    i - s[i]出現的位置, 其他 
15  *                 }
16  */
17 
18 public class P48 {
19     int longestSubstringWithoutDuplication(char[] str){
20         if(str == null || str.length<0) return 0; // 檢測輸入是否合法
21         
22         int[] position = new int[26];    // 記錄字符出現的位置
23         for(int i=0;i<position.length;++i) {
24             position[i] = -1;
25         }
26         
27         int[] dp = new int[str.length];
28         dp[0] = 1;    // 初始化
29         position[str[0]-'a'] = 0;
30         int ans = 1;    // 記錄答案
31         for(int i=1;i<str.length;++i) {
32             int begin = i-dp[i-1];    // dp[i-1]最長不重復子串的起始位置
33             int lastAppear = position[str[i]-'a'];    // 上一次出現的位置
34             if(lastAppear < begin) {
35                 dp[i] = dp[i-1] + 1;
36             }else {
37                 dp[i] = i - lastAppear;
38             }
39             position[str[i]-'a'] = i;
40             if(dp[i] > ans) ans = dp[i];
41         }
42         return ans;
43     }
44     
45     // 測試
46     public static void main(String[] args) {
47         String string = "arabcacfr";
48         int ans = new P48().longestSubstringWithoutDuplication(string.toCharArray());
49         System.out.println(ans);
50         string = "aaa";
51         ans = new P48().longestSubstringWithoutDuplication(string.toCharArray());
52         System.out.println(ans);
53         string = "a";
54         ans = new P48().longestSubstringWithoutDuplication(string.toCharArray());
55         System.out.println(ans);
56         string = "unaocurqgyblpoiqfawer";
57         ans = new P48().longestSubstringWithoutDuplication(string.toCharArray());
58         System.out.println(ans);
59     }
60 }
第一次代碼,仔細觀察可以發現,dp數組可以不用,直接用一個變量代替即可

完善之后的代碼

 1 int longestSubstringWithoutDuplication(char[] str){
 2         if(str == null || str.length<0) return 0; // 檢測輸入是否合法
 3         
 4         int[] position = new int[26];    // 記錄字符出現的位置
 5         for(int i=0;i<position.length;++i) {
 6             position[i] = -1;
 7         }
 8         
 9         int dp = 1;    // 初始化, dp表示以上一個字符結尾的 最大長度
10         position[str[0]-'a'] = 0;
11         int ans = 1;    // 記錄答案
12         for(int i=1;i<str.length;++i) {
13             int begin = i-dp;    
14             int lastAppear = position[str[i]-'a'];    // 上一次出現的位置
15             if(lastAppear < begin) {
16                 dp = dp + 1;
17             }else {
18                 dp = i - lastAppear;
19             }
20             position[str[i]-'a'] = i;
21             if(dp > ans) ans = dp;
22         }
23         return ans;
24     }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM