【剑指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

 

猜你喜欢

转载自www.cnblogs.com/chsobin/p/10582504.html