最长不重复字符串的子字符串

找出并计算给定字符串中最长的不重复的子字符串,假设字符串只包含'a~z'字符,如:'arabcacfr'中 最长不重复子字符串是'acfr',长度为4。

暴力法:枚举所有子串,判断其是否是无重复串,找出最大长度返回。

//枚举出所有子串,若子串为无重复子串 则将长度最长的返回
    public static boolean isUnique(String s, int start, int end) {
    	Set<Character> set = new HashSet<>();
    	for(int i = start; i < end; i++) {
    		Character ch = s.charAt(i);
    		if(set.contains(ch)) {
    			return false;
    		}
    		set.add(ch);
    	}
    	return true;
    }
    
    public static int longestSubstring(String s) {
    	int ans = 0;
    	for(int i = 0; i < s.length(); i++) {
    		for(int j = i+1; j <= s.length(); j++) {
    			if(isUnique(s,i,j)) {
    				ans = Math.max(ans, j-i);
    			}
    		}
    	}
    	return ans;
    }
	public static void main(String[] args) {
		String str = "arabcacfr";
		System.out.println(LongestSubstringWithoutDupilication(str));
		System.out.println(longestSubstring(str));
	}

思路:动态规划算法来降低复杂度,以i为结尾的不重复子字符串的最长长度为f(i), 从左往右遍历字符串的每个字符。当要计算f(i)时,已经得到f(i-1)。每次遍历一个字符,若字符未曾出现,则f(i)=f(i-1)+1,若已经出现,则需要借助一个存放每个字符在字符串中的位置的数组,当i位置的字符已经在前字符串中出现,则从该辅助数组中找到它最近一次出现的位置,i与该位置的距离为d,若d<=f(i-1),则f(i)=d。若d>f(i-1),说明这个字符出现在f(i-1)对应的字符串之前,所以f(i)=f(i-1)+1。

code:

public class NoReaptSubString {
	public static int LongestSubstringWithoutDupilication(String s){
		char[] chas = s.toCharArray();
	    int[] arr = new int[26];
	    int curLength = 0;
	    int maxLength = 0;
	    for(int i = 0; i < arr.length; i++) {//arr数组每个位置存放每个字符上次出现在字符串中位置的下标,初始全为-1
	    	arr[i] = -1;
	    }
	    for(int i = 0; i < chas.length; i++) {
	    	int pre = arr[chas[i]-'a'];
	    	if(pre < 0 || i - pre > curLength) {//若字符从未出现过,或者当前字符与上一次出现的字符的位置差大于当前不重复字串长度,则当前长度加一
	    		curLength++;
	    	}else {
                if(maxLength < curLength) {
	    		    maxLength = curLength;
	    		}
	    		curLength = i - pre; //若字符已出现过,位置差小于当前子串长度,则当前长度就为位置差
	    		
	    	}
	    	arr[chas[i]-'a'] = i;
	    }
	    if(maxLength < curLength) {
			maxLength = curLength;
		}
	    
	    return maxLength;
	    		
	}
	public static void main(String[] args) {
		String str = "arabcacfr";
		System.out.println(LongestSubstringWithoutDupilication(str));
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值