力扣题(2):无重复字符的最长子串

原题:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。
示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成

**解题:**我也是学的官方解法,直接上代码

package test003;

import java.util.HashSet;
import java.util.Set;

/**
 * 无重复字符的最长子串
 */
public class MaxLongString {
    public static int lengthOfLongestSubString(String s){
        //用hashSet集合来放字符串的已经被选择过的未重复的字符
        Set<Character> ooc = new HashSet<>();
        int n = s.length();
        int rk = -1,ans = 0;
        //外循环将每字符串的每一个字符都遍历一遍
        for (int i = 0; i < n; ++i) {
            //如果i!=0,需要将前一个指针的数据删除,因为我们计算有无重复指针是从当前指针向后看的
            if (i!=0){//非起始位置
                ooc.remove(s.charAt(i-1));
            }
            //内循环:每一遍都向后添加字符串HashSet到集合中
            //滑动的指针rk+1在字符串s的范围内,并且HashSet集合中没有相应的字符串
            while(rk+1 < n && !ooc.contains(s.charAt(rk+1))){
                //就将新的字符加入集合中
                ooc.add(s.charAt(rk+1));
                //给指针向后移动一位
                ++rk;
            }
            //每次添加完都将字符串的最新长度与ans比较更新ans的大小
            ans = Math.max(ans,rk+1-i);
        }
        return ans;
    }

    public static void main(String[] args) {
        String s = "abcdabcdebb";
        int i = lengthOfLongestSubString(s);
        System.out.println("无重复字符的最长子串的长度为:"+i);//无重复字符的最长子串的长度为:5
    }
}

总结:

  • 该题要会的前提,第一要熟练掌握String包装类,和HashSet的一些基本方法,如contains,charAt等,了解它的作用
  • 了解解题的基本思想,是滑动窗口的思想,具体看官方的解题思路
  • 了解为什么要用HashSet集合来存储数据:
    HashSet的底层其实是HashMap,二者特征相同,无序,不重复,无索引,所以就算是将同样的值填进去,也会消掉,而查找要不要添加当前窗口的字符时也只需要用一个ooc.contains(s.charAt(rk+1))来实现,contains的底层不是数组的索引遍历查找,而是基于HaspSet哈希数取余的键的精准查找,无疑要比前者快的多。
    而且做了几道题我发现即使涉及到最简单的数字相加,在力扣的官方解题里面也大多鼓励我们用Hash值的思想来存储和查找数据,因为它查找数据确实要比遍历数组的效率更高,这我觉的也是学习算法的精髓,如果只是单纯的遍历对比操作,那么算法的高效性又如何体现呢?

你可能感兴趣的:(数据结构与算法,难度简单,算法题,leetcode,算法,java)