32.Minimum Window Substring-最小子串覆盖(中等题)

最小子串覆盖

  1. 题目

    给定一个字符串source和一个目标字符串target,在字符串source中找到包括所有目标字符串字母的子串。

    注意事项
    如果在source中没有这样的子串,返回”“,如果有多个这样的子串,返回起始位置最小的子串。

  2. 说明

    在答案的子串中的字母在目标字符串中是否需要具有相同的顺序?
    ——不需要。

  3. 样例

    给出source = “ADOBECODEBANC”,target = “ABC” 满足要求的解 “BANC”

  4. 挑战

    要求时间复杂度为O(n)

  5. 题解

本题注意事项中翻译有误,不是返回起始位置最小的子串而是长度最短的子串。
首先对target进行处理,把每个字母的数量以ASCII码的值为地址存入targethash数组。再构建两个指针i,j对source进行遍历,同时将遍历得到的字母的数量计入sourcehash数组,如果不能做到子串覆盖则将j指针后移读入新字母,反之则将i指针后移并从sourcehash数组中减去相应的字母计数,同时比较和记录最小子串,直至遍历完毕。
以样例为例:
ADOBECODEBANC
a.当i=0时,sourcehash为空,显然不满足子串,则将j后移直至j=5时。此时sourcehash的计数为A=1,B=1,C=1,满足子串要求,此时最小子串为ADOBEC,长度为6。最后将A的计数减1,此时sourcehash的计数为A=0,B=1,C=1。
b.当i=1时,由于sourcehash不满足子串要求,则继续步骤a直至j=10。此时sourcehash的计数为A=1,B=2,C=1,最小子串为DOBECODEBA,长度为10。最后将D的计数减1,此时sourcehash的计数为A=1,B=2,C=1。
c.当i=2时,最小子串为OBECODEBA,直至i=6时,sourcehash的计数为A=1,B=2,C=0,将j继续向后移动至最后一位,sourcehash重新满足子串要求。再继续重复上述步骤可获取最小子串。

public class Solution
{
    /**
     * @param source:
     *            A string
     * @param target:
     *            A string
     * @return: A string denote the minimum window Return "" if there is no such
     *          a string
     */
    public String minWindow(String Source, String Target)
    {
        int ans = Integer.MAX_VALUE;
        String minStr = "";
        int[] sourcehash = new int[256];
        int[] targethash = new int[256];
        initTargetHash(targethash, Target);
        int j = 0, i = 0;
        for (i = 0; i < Source.length(); i++)
        {
            while (!valid(sourcehash, targethash) && j < Source.length())
            {
                sourcehash[Source.charAt(j)]++;
                j++;
            }
            if (valid(sourcehash, targethash) && ans > j - i)
            {
                ans = j - i;
                minStr = Source.substring(i, j);
            }
            sourcehash[Source.charAt(i)]--;
        }
        return minStr;
    }

    private void initTargetHash(int[] targethash, String Target)
    {
        for (char ch : Target.toCharArray())
        {
            targethash[ch]++;
        }
    }

    private boolean valid(int[] sourcehash, int[] targethash)
    {
        for (int i = 0; i < 256; i++)
        {
            if (targethash[i] > sourcehash[i])
            {
                return false;
            }
        }
        return true;
    }
}

Last Update 2016.9.26

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值