剑指offer第48题 无重复字符的最长子串(尺取法和动态规划)



问题描述:

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

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1

示例 3:

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

题目链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters



解题思路:

  这题使用暴力法双层循环遍历所有子串会超时,为了避免超时,使用尺取法。尺取法非常适合用于查找字符串中符合特定要求的子串。**尺取法通常是指保留数组的一对下标(起点和终点),然后根据实际情况交替推进两个端点直到得出答案。**这种操作很像尺取虫的爬行方式,故而得名。

类似的题目有:



代码实现:

import java.util.HashSet;

public class text03无重复字符的最长子串 {
	
	public static void main(String[] args) {
		String str = "dvdf";
		System.out.println(lengthOfLongestSubstring(str));
	}
	
	public static int lengthOfLongestSubstring(String s) {
        int res = 0;
        char[] arr = s.toCharArray();
        int star = 0;
        int end = 0;
        while(star<=end && end<arr.length){
        	HashSet<Character> set = new HashSet<Character>();
        	for(int i=star; i<=end; i++){
        		set.add(arr[i]);
        	}
        	if(set.size()==(end-star+1)){  //无重复
        		if(set.size()>res){
        			res = set.size();
        		}
        		end++;
        	}else{   //有重复
        		star++;
        	}
        }
        return res;
    }
}

提交结果:
在这里插入图片描述



  上面的解法可以优化,右指针的遍历不变,左指针的遍历可以进行优化。我们可以在右指针遍历的时候记录字符出现的最后位置。假设右指针当前在的位置是j,当左指针移动时我们可以直接将左指针移动到上一次字符s[j]最后出现的位置i(注意要与左指针原来的位置进行比较,因为字符最后出现的位置不一定更靠后);因为再左指针移动到i位置之前都是会出现重复的,所以可以直接移动到i位置。这样可以加快了左指针的移动速度,减少了重复子串的判断。

代码如下:

    public int lengthOfLongestSubstring(String s) {
    	int res = 0;
        char[] arr = s.toCharArray();
        Map<Character,Integer> dic = new HashMap<Character, Integer>(); //记录字符最后出现的位置。
        //j表示右指针,i表示左指针
        int i = -1;
        for(int j=0; j<arr.length; j++) {
        	if(dic.containsKey(arr[j])) {
        		i = Math.max(dic.get(arr[j]), i);  //更细左指针,注意要比较,因为字符最后出现的位置不一定更靠后
        	}
        	dic.put(arr[j], j);  //记录字符出现的组后位置
        	res = Math.max(res, j-i);	
        }
        return res;
    }	 

提交结果:
在这里插入图片描述
这个优化的方法本质上和动态规划右类似的地方。

参考文章:
双指针和动态规划

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥自在”

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值