408算法练习——无重复的最长子串
无重复的最长子串
题目连接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/
一、问题描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
     请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
二、设计思路
判断有无重复:因为重复的字母的位置不确定,所以在遍历到后面的字符时为了得知当前字符是否被遍历过,就需要对前面的遍历进行一个记录,可以设计一个数组,因为本题给出的字符串是全英文的,那么就可以定义一个大小为26的数组,第一个位置表示a是否出现过,第26个位置表示z是否出现过。当然也可以直接使用<key,value>实现,这样查找起来也很方便,使用数组的难度在于怎么把当前字母散列到这个数组中,为了实现随机存取,就必须对当前遍历到的字符进行散列,然后再查找。
字符的散列:java中char型变量前128位是按照ASCII码排列的,ASCII码表中a的大小为97,所以我们在得到每个字符后可以将这个字符对97取余,这样就能映射到数组中,注意这样操作的前提是知到字符串可能包含的所有字符类型。否则还是使用hashmap更加简单。
遍历数组:可以采用滑动窗口的方式来对数组进行遍历,例如abcabcbb,我们可以先固定a,然后向后遍历找出从a开始的最长无重复子串,然后固定b,找出以b为开始的最长无重复子串,依次类推,就好像有一个窗口在字符串上滑动一样。下面给出官方解答:
  
1 public int lengthOfLongestSubstring(String s) { 2 // 哈希集合,记录每个字符是否出现过 3 Set<Character> occ = new HashSet<Character>(); 4 int n = s.length(); 5 // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动 6 int rk = -1, ans = 0; 7 for (int i = 0; i < n; ++i) { 8 if (i != 0) { 9 // 左指针向右移动一格,移除一个字符 10 occ.remove(s.charAt(i - 1)); 11 } 12 while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) { 13 // 不断地移动右指针 14 occ.add(s.charAt(rk + 1)); 15 ++rk; 16 } 17 // 第 i 到 rk 个字符是一个极长的无重复字符子串 18 ans = Math.max(ans, rk - i + 1); 19 } 20 return ans; 21 }
三、动态规划
未完待续
                    
                
                
            
        
浙公网安备 33010602011771号