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     }

 

三、动态规划

  未完待续

posted @ 2021-07-11 21:30  瑜琦  阅读(98)  评论(0)    收藏  举报