LeetCode算法题3——无重复字符的最长子串

如题:

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

示例:

给定 "abcabcbb" ,没有重复字符的最长子串是 "abc" ,那么长度就是3。

给定 "bbbbb" ,最长的子串就是 "b" ,长度是1。

给定 "pwwkew" ,最长子串是 "wke" ,长度是3。请注意答案必须是一个子串"pwke" 是 子序列  而不是子串。

 

我的做法简单易懂,为暴力解法,两个循环遍历所有情况,时间复杂度大约是O(n^2)。代码如下

public class Problem3 {

    public static int lengthOfLongestSubstring(String s) {
    	
    	int maxLen = 0;
    	
    	if(s == null) {
    		maxLen = 0;
    	}
    	else if(s.length() == 1) {
    		maxLen = 1;
    	}
    	
    	else {
    		for(int i = 0; i < s.length(); i ++) {
            	Set<String> characters = new HashSet<>();
            	characters.add(s.substring(i, i + 1));
            	for(int j = i + 1; j < s.length(); j ++) {
            		if( ! characters.contains(s.substring(j, j + 1))){
            			characters.add(s.substring(j, j + 1));
            		} else {
            			break;
        			}
        		}
            	maxLen = ((maxLen < characters.size()) ? characters.size() : maxLen);
        	}
        }
    	return maxLen;
	}
}

我觉得这个算法效率不能再低了,提交之后居然通过了,不过正如我所想的效率太低了,只超过了9%的java程序。

之后翻看了一个超过90%的算法,代码如下:

public class Amazing {
	public static int lengthOfLongestSubstring(String s) {
	    int ans =0;
	    int[] ss = new int[128];
	    for(int i=0,j=0;i<s.length();i++){
	        j = Math.max(ss[s.charAt(i)],j);
	        System.out.print(s.charAt(i));
	        System.out.println(ss[s.charAt(i)]);
	        ans = Math.max(ans,i-j+1);
	        ss[s.charAt(i)]=i+1;
	    }
	    return ans;
	}

}

浏览一番,真的是差距太大啊。时间复杂度竟然变成了O(n)。

第一次看这个算法,还这么几个疑问:

1、数组ss的成员ss[s.charAt(i)],数组的成员可以用字符表示?这种用法是我第一次见到的。看到ss数组大小为128,大概知道是什么用途了。

2、j 和 ans 分别是代表什么的变量?这个问题也很快解决了,j 是最大不重复子序列的开头,而 ans 则是最大不重复子序列的长度。

解决了上述问题,这个算法看起来就有些好理解了。

要想不重复的子序列最长,那么不就是子序列的开头不是序列的头部,就是是两个相同的字符的第二个(如"abnbam"子序列开头为b)。该算法通过遍历序列,

ss数组存储的是对应字符上一次出现的位数,eg.如果String s = “abva”,那么a第一次迭代到时 ss[a] = 0,同时将ss[a]修改为1。第二次迭代到 a 时,ss[a] = 1,因为上一次 a 出现再第一位,同时将 ss[a]修改为4。

仔细看了几遍,终于明白了大概。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值