求字符串内不包含重复字符的最长子串的集合

本文介绍了两种不同的算法来寻找给定字符串中最长的不含重复字符的子串。第一种方法使用循环遍历和哈希集,其时间复杂度为O(n²);第二种方法通过运用哈希映射优化了查找过程,实现O(n)的时间复杂度。

方法一:循环遍历,采用Set保存数据,复杂度O(n^2)

private static Set<String> getSubList(String str) {
		if (null == str || str.trim().length() == 0) {
			return null;
		}
		Set<String> result = new HashSet<String>();
		int maxLength = 0;
		StringBuilder sb = new StringBuilder();
		char[] array = str.toCharArray();
		int length = array.length;
		for (int i = 0; i < length; i++) {
			int j = i + 1;
			sb.delete(0, sb.length());
			sb.append(array[i]);
			while ((length - j) >= maxLength) {
				sb.delete(0, sb.length());
				for (; j < length; j++) {
					if (sb.toString().contains(String.valueOf(array[j]))) {
						break;
					} else {
						sb.append(String.valueOf(array[j]));
					}
				}
//				System.out.println(j + "," + sb.toString());
				if (sb.length() > maxLength) {
					maxLength = sb.length();
					result.clear();
					result.add(sb.toString());
				} else if (sb.length() == maxLength) {
					result.add(sb.toString());
				}
			}
		}
		return result;
	}

方法2:

采用一个map来做中间缓存,用list保存结果,map的key存储的是字符,value存储的是该字符当前的位置,首先设置一个当前current位置,默认从0开始,那么从开始遍历字符串,如果map当中不包含这个字符,那么用这个字符当前所在的位置减去current位置,然后与最大长度做比较,选大的成为最大长度,然后把当前字符的以及位置放入map,同时把从current位置的字符到current+maxLength位置的字符组成子串放入一个list中,保存前需要判断当前list中已经保存的字符的长度是否大于将要保存的字符长度,小于则将list清除,复杂度 O(n)

public static List<String> getSubList2(String str){
		if (null == str || str.trim().length() == 0) {
			return null;
		}
		Map<Character,Integer> tempMap = new HashMap<>();
		List<String> result = new ArrayList<String>();
		StringBuilder sb = new StringBuilder();
		int maxLength = 0;
		char[] array = str.toCharArray();
		int length = array.length;
		int current = 0;
		for(int i=0;i<length;i++){
			if(tempMap.containsKey(array[i])){
				current = Math.max(tempMap.get(array[i])+1,current);
//				System.out.println((i-current+1)+","+maxLength);
				if((i-current+1)>maxLength){
					maxLength = i-current+1;
					sb.delete(0, sb.length());
					for(int j=current;j<current+maxLength;j++){
						sb.append(array[j]);
					}
					if(result.size() > 0){
						if(result.get(0).length()<maxLength){
							result.clear();
						}
					}
					result.add(sb.toString());
				}else if((i-current+1) == maxLength){
					sb.delete(0, sb.length());
					for(int j=current;j<current+maxLength;j++){
						sb.append(array[j]);
					}
					if(result.size() > 0){
						if(result.get(0).length()<maxLength){
							result.clear();
						}
					}
					result.add(sb.toString());
				}
			}else{
				
//				System.out.println((i-current+1)+","+maxLength);
				if((i-current+1)>maxLength){
					maxLength = i-current+1;
					sb.delete(0, sb.length());
					for(int j=current;j<current+maxLength;j++){
						sb.append(array[j]);
					}
					if(result.size() > 0){
						if(result.get(0).length()<maxLength){
							result.clear();
						}
					}
					result.add(sb.toString());
				}else if((i-current+1) == maxLength){
					sb.delete(0, sb.length());
					for(int j=current;j<current+maxLength;j++){
						sb.append(array[j]);
					}
					if(result.size() > 0){
						if(result.get(0).length()<maxLength){
							result.clear();
						}
					}
					result.add(sb.toString());
				}
			}
			tempMap.put(array[i], i);	
		}
//		System.out.println(maxLength);
		return result;
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值