longest-substring-without-repeating-characters(最长不重复字符子串)

原题链接
思路一:
枚举每个开头, 用map容器统计以此字母开头的每个字母的个数,发现扫描到某个字母出现过了就得出以前面开头的字母的最长不含重复字符的串长度。
比如 abca 以 a开头,扫描序列,发现扫描到 第四个字母的时候是 a,a前面出现过了,得出当前最长的串的长度是3,即abc。然后以第二个字母b开头,发现最长的串是bca, 同样的做法,以第三个c开头,发现最长的串是ca …
时间复杂度是O(N*N) N是字符串的长度


class Solution {
public:
    int lengthOfLongestSubstring(string s) {
		
		int length = s.length();
		if(length == 0)
			return 0;
		int res = 0;
		for(int i = 0; i < length; i++){//枚举每个开头
			map<char, int>mp;
			int curMax = 0;
			mp[s[i]]++;//当前开头的字符出现次数加1
			int j; 
			for(j = i + 1; j < length; j++){//枚举前面,看能否构成的最长的不含重复的串
				if(mp[s[j]])//出现过了。最长的串是i到j-1这部分的串
					break;
				else
					mp[s[j]]++;
			}
			curMax = j - i; 
			res = res > curMax ? res : curMax;//更新最长的

		}

		return res;
        
    }
};

思路二:
**建立一个滑动窗口,滑动窗口的串是不含重复字符的串。**一开始设一指针指向最长的不含重复字符的串的开头,相当于窗口的左边, 设定另一个指针作为窗口的右边,活动右窗口指针,发现如果没有重复的话继续滑动窗口, 如果重复的话就把左窗口滑动到重复字符的下一个的字符上。
比如求 abcdbefg 这个最长不重复子串,左窗口指向0号位置, 右窗口指向0,移动右窗口,发现移动到4号位置,即b的时候和前面的1号位置的b重复了, 那么就把左窗口移动到1号的下一位,即c上。滑动窗口的时候同时更新最大长度。


class Solution {
public:
    int lengthOfLongestSubstring(string s) {
		
		int length = s.length();
		if(length == 0)
			return 0;
		int res = 0;
		int * hash = new int[130];
		//建立每个字符的出现的位置的映射。比如
		//hash[122]=1.表示字符z出现的位置是1.
		for(int i =  0; i < 130; i++){
			hash[i] = -1;
		}

		int left = 0, right = 0;//左窗口和右窗口

		while(left < length && right < length){
			//如果字符没有出现过,或者字符在左窗口前面(相当于也是没有出现过)
			if(hash[(int)s[right]] == -1 || hash[(int)s[right]] < left){
				hash[(int)s[right]] = right;//记录这个字符出现的位置
				res = max(res, right - left +1);//更新最大长度
				right++;//窗口移动到下一位
			
			}
			else{//如果字符出现过了
				//更新不重复的最长子串
				res = res > (right - left) ? res : (right - left);
				left = hash[(int)s[right]] + 1;//更新左窗口的位置(重复出现的字符的下一个位置)
				hash[(int)s[right]] = right;//更新重复字符的位置
				right++;

			}
		}
		return res;
        
    }
};

JAVA版本:

注意的地方,用s.charAt(index)获取在index处的字符。

package Leetcode;


public class Solution {
    public static int lengthOfLongestSubstring(String s) {
        int length = s.length();
        if(length <= 0)
        	return 0;
        
        int []hash = new int[123];
        for(int i = 0; i < 123; i++) {
        	hash[i] = -1;
        }
        int left = 0, right = 0;
        int res = 1;
        while(left < length && right <length) {
        	if(hash[ (int)s.charAt(right) ] == -1 || hash[ (int)s.charAt(right) ] < left) {
        		res = Math.max(res, right - left +1);
        		hash[(int)s.charAt(right)] = right;
        		right++;
        	}
        	else {
        		res = Math.max(res, right - left);
        		left = hash[(int)s.charAt(right)] +1;
        		hash[(int)s.charAt(right)] = right;
        		right++;
        		
        	}
        	
        }
        
        return res;
    }
    
    public static void main(String args[]) {
    	String str = "qopubjguxhxdipfzwswybgfylqvjzhar";
    	int res = lengthOfLongestSubstring(str);
    	System.out.println(res);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值