lintcode--最小子串覆盖

本文介绍了一种寻找包含目标字符串所有字符的最小子串算法。通过双指针与哈希表结合的方法,在源字符串中查找符合条件的最短子串。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

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

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

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

思路讲解:
我们首先将目标字符串映射到一个大小为128的hash_target数组,然后我们建立一个同样的hash数组,然后遍历source这个字符串,并用两个指针begin和end,每次都将字符与target的没以恶搞字符比较,然后将其在hash中对应的位置加一,并将其与hash_target比较,如果是,则说明找到一个子串可以包含target的,然后我们将从begin开始,逐个删除字符(这一步是为了得到最小的子串包含target的),如果删除之后,hash还是比hash_target大,说明找到了一个较小的子串;如果没有就从end开始继续遍历source,这样就可以得到了最小的子串。
举个栗子:
ADOBECODEBANC
a.当begin=0时,hash为空,显然不满足子串,则将end后移直至end=5时。此时hash的计数为A=1,B=1,C=1,满足子串要求,此时最小子串为ADOBEC,长度为6。最后将A的计数减1,此时hash的计数为A=0,B=1,C=1。
b.当begin=1时,由于hash不满足子串要求,则继续步骤a直至end=10。此时hash的计数为A=1,B=2,C=1,最小子串为DOBECODEBA,长度为10。然后将D去掉,此时hash的计数为A=1,B=2,C=1。
c.当begin=2时,最小子串为OBECODEBA,直至begin=6时,hash的计数为A=1,B=2,C=0,将end继续向后移动至最后一位,hash重新满足子串要求。再继续重复上述步骤可获取最小子串。

代码详解:

class Solution {
public:
    /*
     * @param source : A string
     * @param target: A string
     * @return: A string denote the minimum window, return "" if there is no such a string
     */
    string minWindow(string &source , string &target) {
        // write your code here
        int length=target.length();

        if(source=="")
        return "";
        vector<int> hash(128,0);
        vector<int> hash_target(128,0);

        for(int i=0;i<length;i++)//初始化target的映射
        {
            hash_target[target[i]]++;
        }

        int begin,end;
        begin=0,end=0;

        int sublength=INT_MAX,low=0,high=0;
        while(end<source.length())
        {

            if(!judge_contain_target(hash,hash_target))//如果没有找到子串,就继续找
            {
                for(int i=0;i<length;i++)
                {
                    if(target[i]==source[end]){
                        hash[target[i]]++;
                        break;
                    }

                }
                end++;
            }
            if(judge_contain_target(hash,hash_target)){//如果找到子串,就看是否存在较短的子串
                if(sublength>(end-begin)){
                    sublength=end-begin;
                    low=begin;
                    high=end;
                }
                for(int i=0;i<length;i++)
                {
                    if(target[i]==source[begin]){
                        hash[target[i]]--;
                        break;
                    }
                }
                begin++;
            }
        }

        while(judge_contain_target(hash,hash_target))//特殊情况的处理例如:aaaaaaaabcd和abcd
        {
           if(sublength>(end-begin)){
                    sublength=end-begin;
                    low=begin;
                    high=end;
                }
                for(int i=0;i<length;i++)
                {
                    if(target[i]==source[begin]){
                        hash[target[i]]--;
                        break;
                    }
                }
                begin++; 
        }

        if(sublength==INT_MAX){
            return "";
        }
        else{
            return source.substr(low,sublength);
        }
    }
    bool judge_contain_target(vector<int>hash,vector<int>hash_target)//判断是否找到了子串
    {
        for(int i=0;i<128;i++)
        {

            if(hash[i]<hash_target[i]){
                return false;
            }
        }
        return true;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值