无重复的最长字符串(Java)Leetcode

1.题目

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:

输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:

输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:

输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
示例 4:

输入: s = “”
输出: 0
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters

2.思路

1.最开始自己想的是用一个for循环,两个函数方法,一个函数是具体判断此时的字符是否与之前的字符重复了,一个函数是对字符串进行操作,再调用判断函数,每次记得更新字符串最大长度和新的字符串开始位置。但是后来提交有一个用例报错“dvdf”,此时突然醒悟,需要用两个for循环,一个for循环只能不断的往后找,然后修改之后提交,运行超时了,时间复杂度此时已经比较大了,输入测试的字符串也很长很长。
自己写的内联代码片
判断是否与之前的字符重复:

public static boolean isRepeat(String s, int index, int m) {
    
    
		for(int i = index; i <= m; i++) {
    
    
			for(int j = i + 1; j <= m; ++j) {
    
    
				if(s.charAt(i) == s.charAt(j))
					return false;
			}
		}
		return true;
	}

具体操作:

public static int lengthOfLongestSubstring(String s) {
    
    
		if(s.length() == 1) {
    
    
			return 1;
		}
    	int count = 1;//记录不重复子字符串的长度
    	int index = 0;//记录起始字符的下标
    	int record = 0;//当找到一个子字符串时,将此时长度保存到record里面,便于下一次比较大小
    	for(int j = 0; j < s.length(); ++j) {
    
    
    		count = 1;
    		index = j;
    		for(int i = j+1; i < s.length(); ++i) {
    
    
        	    if(isRepeat(s,index,i))	{
    
    
        	    	count += 1;
        	    } else {
    
    
        	    	record = record >= count ? record: count;
        	    	//注意:必须在else里面判断record和count的值,不能在else语句外面,否则record取不到最大值
            	    	
        	   //此时,找到了一个不重复的子字符串,记录下此时长度的字符串
        	    	index = i;// 重新记录下一次找不重复字符串起始位置
        	    	count = 1;//将count重新置为1
        	    }
        	   record = record >= count ? record: count;//还需要判断一次,避免没有进入else语句,比较record和count的大小,record总是保留大的值     	
        	}
    		record = record >= count ? record: count;
    	}
    	return record;	
    }

2.然后想不到方法了,去评论区看的题解。很简洁,了解到了一个新名词“滑动窗口”,滑动窗口一般用于求解连续区间的问题
代码如下:

public static int lengthOfLongestSubstring(String s) {
    
    
	        int n = s.length(), ans = 0;
	        Map<Character, Integer> map = new HashMap<>();
	        for (int end = 0, start = 0; end < n; end++) {
    
    
	            char alpha = s.charAt(end);
	            if (map.containsKey(alpha)) {
    
    
	                start = Math.max(map.get(alpha), start);
	            }
	            ans = Math.max(ans, end - start + 1);
	            map.put(s.charAt(end), end + 1);
	        }
	        return ans;
	   }

原文链接: link.
用了一个HashMap来存储,减少了很多不必要的循环,思路大致相同。
3.学习心得:目前对集合,Map这一块做题用的少,但是有些题用起来会使题目变得简洁,而且也没想道过可以用Map来存储简化,基础还是不够扎实。自己用两个for循环也做了很久,不断调试,怕自己懵了已经开始写注释了。加油!

猜你喜欢

转载自blog.csdn.net/balder_girl/article/details/113606495