leetcode:Longest Substring Without Repeating Characters

159 篇文章 0 订阅

问题描述:

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1.

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

 

问题分析

    这个问题看起来还是比较简单的。需要找一个字符串里最大不包含重复元素的子串。我们可以根据一些串的示例来分析一下:

     假定我们有如下的一个字符串:

      

     我们最初的想法可以是这样,通过将每个字符和它所在的索引保存到一个map里,每次将一个元素加入到map的时候事先判断一下map里是否存在该字符,如果存在则发现有重复的元素,需要做一些处理。否则直接将该元素和它所在的索引加入到map中。既然要取得最大的子串长度,我们需要有一个变量来记录当前串的起始位置以及当前的结束位置。

     在上述的示例中,假设分别以i, j表示当前串的开始和结束。当碰到一个重复的元素时,其情景如下图:

     

     这个时候我们该怎么办呢?为了计算最大的子串,我们应该将起始点移到这个已经存在的这个节点后面。也就是b这个位置上。也就是如下图这样:

    

    这个时候,我们需要更新原来那个重复元素映射的新位置,也就是将a映射的值设置为j。当然,因为前面这个示例有一点特殊,还有一个地方我们忽略了。就是假设i这个元素它并不是后面找到重复的地方,而是在它稍微后面一点的地方,比如下图这样:

    

    这个时候,我们碰到重复元素b,应该将i移到b后面。但是这个时候我们也应该修改map。因为map里应该只保存从i到j之间的所有元素,所以从i到b之间的所有元素应该被移除掉。

    这样,经过这些讨论我们就有了这么一个思路。首先记录起始和终止标识i, j为0。然后j开始向后遍历,每次遍历就检查是否在map里存在该元素。如果不存在则直接加入到map中。如果存在,则从i到它找到存在的那个元素之间将这些元素从map里去掉,然后设置i为重复元素后面的那个位置,再更新冲突的位置为j。这样可以得到如下的代码:

 

public class Solution {
    public int lengthOfLongestSubstring(String s) {
        if(s == null || s.length() == 0) return 0;
        int len = 0;
        Map<Character, Integer> map = new HashMap<>();
        for(int i = 0, j = 0; j < s.length(); j++) {
            Character c = s.charAt(j);
            if(map.containsKey(c)) {
                int pos = map.get(c);
                for(int k = i; k <= pos; k++) map.remove(s.charAt(k));
                i = pos + 1;
            }
            map.put(c, j);
            len = Math.max(len, j - i + 1);
        }
        return len;
    }
}

     总体来说,这个解法的时间复杂度为O(n)。

 

总结

    这个问题并不复杂,主要是需要细心的分析一下就可以了。把图画出来就好办。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值