Coding Puzzels - 64 最小的窗口子字符串

给定一个字符串S和一个字符串T,求S中的最小的窗口,其中包含了T中的字符。算法的复杂度为O(n)。

例如,S="ADOBECODEBANC", T="ABC"。最小的窗口是“BANC”。注意如果不存在覆盖了T中的所有的字符的窗口,返回空字符串。如果有多个这样的窗口,确保S中总有一个唯一的最小窗口。


package com.algo.coding.puzzles;

import java.util.HashMap;

public class MinWindow64 {
	
	public String minWin(String resource, String target){
		HashMap expectCountHs = new HashMap();
		HashMap appearCountHs = new HashMap();
		int minV = Integer.MAX_VALUE;
		int start = 0;
		int end = 0;
		int winStart = 0;
		for(int i = 0; i < target.length(); i++){
			char c = target.charAt(i);
			Object countObj = expectCountHs.get(c);
			int count;
			if(countObj != null){
				count = (int) countObj;
				count ++;
			}else{
				count = 1;
			}
			expectCountHs.put(target.charAt(i), count);
		}
		int appearChars = 0;
		for(int winEnd = 0; winEnd < resource.length(); winEnd++){
			char c = resource.charAt(winEnd);
			int expectCount = this.getCount(expectCountHs, c);
			/*
			 * only关心Target里有的字符
			 */
			if(expectCount > 0){
				int appearCount = this.getCount(appearCountHs, c);
				appearCount++;
				appearCountHs.put(c, appearCount);
				/*
				 * 当出现了期待的字符,会计算期待字符的个数。
				 */
				if(expectCount >= appearCount){
					appearChars++;
				}
			}
			
			/*
			 * appearCountHs 代表win start 和 win end 区间内字符串出现的次数。
			 * (在target里有的字符会比较存在的次数和target里的次数,严格等于appearCountHs。 在target里没有的字符,有可能出现-1,这不影响。)
			 * appearCountHs (A=1 B=1 C=1), expectCountHs (A=1 B=1 C=1), winStart = 0, winEnd = 5 没有运行 while
			 * appearCountHs (A=2 B=2 C=1), expectCountHs (A=1 B=1 C=1), winStart = 0, winEnd = 10 运行完下面的while,变成 winStart = 5, winEnd = 10 
			 * appearCountHs (A=1 B=1 C=2), expectCountHs (A=1 B=1 C=1), winStart = 5, winEnd = 12 
			 * 当C的appearCount > expectCount, winStart ++, 其他字符expectCount == 0 运行完下面的while,变成 winStart = 9, winEnd = 12 
			 * */
			char startChar = resource.charAt(winStart);
			int startAppearCount = this.getCount(appearCountHs, startChar);
			int startExpectCount = this.getCount(expectCountHs, startChar);
			/*
			 * 当期待区间内出现所有期待的字符,才运行。去掉这个条件,minV最小会是1。
			 */
			if(appearChars == target.length()){
				while(startAppearCount > startExpectCount || startExpectCount == 0){
					startAppearCount --;
					appearCountHs.put(startChar, startAppearCount);
					winStart ++;
					startChar = resource.charAt(winStart);
					startAppearCount = this.getCount(appearCountHs, startChar);
					startExpectCount = this.getCount(expectCountHs, startChar);
				}
				if(minV > winEnd - winStart + 1){
					minV = winEnd - winStart + 1;
					start = winStart;
					end = winEnd;
				}
//			return resource.substring(start, end);
			}
		}
		return resource.substring(start, end+1);
		
	}
	
	public int getCount(HashMap hs, char c){
		Object obj = hs.get(c);
		int count = 0;
		if(obj != null){
			count = (int) obj;
//			count ++;
		}
		return count;
	}
	

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		String resource = "ADOBECODEBANC";
//		String target = "ABC";
//		String resource = "abccbaddac";
//		String target = "abcd";	
		String resource = "aabcadbbbcca";
		String target = "abcd";			
		MinWindow64 minWin = new MinWindow64();
		System.out.println(minWin.minWin(resource, target));;

	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值