数据结构与算法

数据结构与算法

task05

1.无重复字符的最长字符

思路都在注释里了
 public int lengthOfLongestSubstring(String s) {
       //如果s为空,length不大于0,是一个空串,就没有向下执行的必要了
        if(s != null && s.length() > 0 && s != ""){
            //String -> char[]
            char[] strChar = s.toCharArray();
            // 存储最长字串 key:char值,value:index下标
            ArrayList<String> maxStr = new ArrayList<>();
            //临时的字串存储空间
            ArrayList<String> tempStr = new ArrayList<>();
            //循环
            for(int i=0; i<strChar.length; i++){
                //char -> String
                String str = new String(new char[]{strChar[i]});
                //判断str是否存在于tempStr中
                if(tempStr.contains(str)){
                    //先判断tempStr的长度是否大于等于maxStr的长度,大于,才能将最长字串覆盖
                    if(tempStr.size() > maxStr.size()){
                        maxStr = new ArrayList<>(tempStr);
                    }
                    //存储重复字符
                    int reIndex = tempStr.indexOf(str);
                    // 删除tempStr中的重复字节及其之前的字符
                    for(int j=0;j<=reIndex;j++){
                        tempStr.remove(0);
                    }
                }
                //将当前字符存入tempStr中
                tempStr.add(str);
            }
            //最终判断
            if(tempStr.size() > maxStr.size()){
                maxStr = tempStr;
            }
            //返回最长字串的长度
            return maxStr.size();
        }
        return 0;
    }

2.串联所有单词的子串

参考了leetcode的题解,思路很清晰,用了滑动窗口。
模拟了一个最大长度为给定单词长度之和的滑块(words.length * len)。让滑块在字符串S上滑动,通过判定滑块捏的字符是否匹配给定单词来存储下标。 然后做了一些优化处理。

1.首先我缓存了所有words中个word 在字符S中的下标。在后续比较中直接比较map,减少循环次数。
2.滑块每次滑动的长度为单词的长度 len。这样滑块中间的数据不用重复比较。滑块分别从下标 0 到len-1共循环滑动 len次。
3.下标为0时,滑块判定的数据为 0, len , 2 * len, 3*len…
4.下标为1时,滑块判定的数据为 1,len +1, 2 len+1 ,3len+1…
5.循环构建滑块,从map中缓存在下标开始构建,当滑动到不在map中的单词时,销毁滑块。直到下一个有效下标重新构建。
6.在滑动滑块的过程中,记录滑块内有效的单词个数 flagNum.每次滑动后。7.如果有效的单词个数与总单词个数相同,时滑块内的数据就是我们所要的。

public static List<Integer> findSubstring(String s, String... words) {
`List<Integer> list = new ArrayList<>();
	if (s.length() == 0 || words.length == 0)
		return list;
	int len = words[0].length();
	if (s.length() < words.length * len)
		return list;
	int idx = -1;
	char[] sCharS = s.toCharArray();
	Set<Integer> allSet = new HashSet<Integer>();// 存储在字符串S所有匹配的下标 去重 排序
	Map<String, Integer> wordMap = new HashMap<>();// 存储 word中各个单词的个数
	Map<Integer, String> idxMap = new HashMap<>();// 存储字符串s各下标对应的单词
	for (String word : words) {
		if (wordMap.containsKey(word)) {
			wordMap.put(word, wordMap.get(word) + 1);
			continue;
		}
		char[] tem = word.toCharArray();
		while ((idx = indexOf(sCharS, sCharS.length, tem, len, idx + 1)) > -1) {
			idxMap.put(idx, word);
			allSet.add(idx);
		}
		wordMap.put(word, 1);
	}

	String word;
	int slideLen = len * words.length;// 滑块长度
	int n;// 临时变量
	Map<String, Integer> temWordMap = new HashMap<>();
	for (int k = 0; k < len; k++) {
		int flagNum = 0;// 表示滑块中有效的单词个数
		for (int i = -1, j = k; j <= sCharS.length - len; j += len) {
			if (allSet.contains(j)) {
				if (i == -1) {// 初始化滑块
					i = j;
					flagNum = 0;
					temWordMap.clear();
					temWordMap.putAll(wordMap);
				}
				// 滑块长度增加 在尾部添加
				word = idxMap.get(j);
				n = temWordMap.get(word) - 1;
				temWordMap.put(word, n);
				if (n >= 0)
					flagNum++;
				if (j - i >= slideLen) {// 滑块长度减小 吐出头部数据
					word = idxMap.get(i);
					n = temWordMap.get(word) + 1;
					temWordMap.put(word, n);
					if (n > 0)
						flagNum--;
					i += len;
				}
				if (flagNum == words.length)
					list.add(i);
			} else {
				i = -1;// j所在的位置不是给定的单词 ,销毁滑块
			}
		}
	}
	return list;

}

3.替换子串得到平衡字符串

应用了滑动窗口
 public int balancedString(String s) {
        int q = 0;
        int w = 0;
        int e = 0;
        int r = 0;
        int begin = 0;
        int cur = 0;
        int res = 100000;
        int len = s.length();
        while(cur<len){
            if(s.charAt(cur)=='Q')
                q++;
            else if(s.charAt(cur)=='W')
                w++;
            else if(s.charAt(cur)=='E')
                e++;
            else
                r++;   
            cur++;
        }
        if(q==w && w==e && e==r)
            return 0;
        
        cur=0;
        while(cur<len){
            if(s.charAt(cur)=='Q')
                q--;
            else if(s.charAt(cur)=='W')
                w--;
            else if(s.charAt(cur)=='E')
                e--;
            else
                r--;
            while(q<=len/4 &&w<=len/4 &&e<=len/4 &&r<=len/4 &&begin<=cur){
                res = Math.min(res,cur-begin+1);
                if(s.charAt(begin)=='Q')
                    q++;
                else if(s.charAt(begin)=='W')
                    w++;
                else if(s.charAt(begin)=='E')
                    e++;
                else
                    r++; 
                begin++;
            }
            cur++;
        }
        return res;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值