Leetcode中字符串与子串 I

本文详细解析了三个经典的字符串子串问题:最长无重复字符子串、最小窗口子串及包含所有单词的子串。提供了详细的解题思路与C++代码实现。

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

求子串应该也是字符串题目的一大分支吧。


题目一:Longest Substring Without Repeating Characters

Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for "abcabcbb" is "abc", which the length is 3. For "bbbbb" the longest substring is "b", with the length of 1. 

思路:没思路,一看到substring什么的我就懵%>_<% 这道题跟循环字符串没有什么关系,不能混淆了。这里只是要求字串里没有重复字符串。对于字符串的重复判断,可以采用a[256]来充当hash table了,这个最方便,可以减少大量查询时间。没有思路,来个暴力BF。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
      int n = s.length();
      int i = 0, j = 0;
      int maxLen = 0;
      bool exist[256] = { false };
      while (j < n) {        //利用两个指针从左到右遍历
        if (exist[s[j]]) {
          maxLen = max(maxLen, j-i);
          while (s[i] != s[j]) {
            exist[s[i]] = false;
            i++;
          }
          i++;
          j++;
        } else {
          exist[s[j]] = true;
          j++;
        }
      }
      maxLen = max(maxLen, n-i);
      return maxLen;
    }
};

题目二: Minimum Window Substring

Given a string S and a string T, find the minimum window in S will contain all the characters in T in complexity O(n). For example, S="ADOBECODEBANC", T="ABC", Minimum Window is "BANC".

思路:这道也是一道难题。难题都有很巧的方法,只是碰巧我都想不到。求助于discuss。这大道题有点类似于有字典,但和前面不一样,这里需要对每个字符计数。建立两个字典needToFound[256]和hasFound[256]. 前者就是统计需要查询的字符及其个数,是不变的;后者这是当前已经访问了字符及个数。如果hasFound达到了预计的个数(T.length()),则找到了一个候选解。除了建表之外,还有这道题也是通过两个指针从左到右访问的 start and end 分别表示字串的开始于结束。

class Solution {
public:
    string minWindow(string S, string T) {
        int needToFound[256]={0};
        int hasFound[256]={0};
        
        int minWindowlen=INT_MAX;
        int minWindowBeg=-1;
        int minWindowEnd=-1;
        int count=0;
        
        for(int i=0; i<T.length(); i++)
            needToFound[T[i]]+=1;
        
        for(int beg=0, end=0; end<S.length(); end++){
            if(needToFound[S[end]]==0)
                continue;
            hasFound[S[end]]+=1;
            if(hasFound[S[end]]<=needToFound[S[end]])
                count++;
            if(count==T.length()){
                while(hasFound[S[beg]]==0||hasFound[S[beg]]>needToFound[S[beg]]){//类似于水满了,要溢出一部分
                    if(hasFound[S[beg]]>needToFound[S[beg]])
                        hasFound[S[beg]]--;
                    beg++;
                }
                int windowlen=end-beg+1;
                if(windowlen<minWindowlen){
                    minWindowlen=windowlen;
                    minWindowBeg=beg;
                    minWindowEnd=end;
                }
                //count=0;
            }
        }
        if(minWindowBeg==-1) return "";
        string res=S.substr(minWindowBeg, minWindowlen);
        return res;
    }
};

题目三: Substring with Concatenation of All Words

You are given a string, S, and a list of words, L, that are all of the same length. Find all starting indices of substring(s) in S that is a concatenation of each word in L exactly once and without any intervening characters. For example, given S: "barfoothefoobarman", L: ["foo", "bar"], you should return the indices: [0, 9]

思路:这道题BF能解。

class Solution {
public:
    
    vector<int> findSubstring(string S, vector<string> &L) {
            int ll=L.size();
            int wl=L[0].length();
            vector<int> res;
            unordered_map<string, int> dict;
            
            for(int i=0; i<ll; i++){
                dict[L[i]]+=1;
            }
            int n=S.length(); //又给自己跪了,S.length()返回无符号类型
            for(int i=0; i<=n-ll*wl; i++){
                //加上下面这句话可以免去拷贝map的时间!
                if(dict.find(S.substr(i, wl))==dict.end())
                    continue;
                    
                unordered_map<string, int> tmp(dict);
                int j;
                for(j=i; j<i+wl*ll; j=j+wl){
                    string ss=S.substr(j, wl);
                    if(tmp.find(ss)==tmp.end() || tmp[ss]==0){
                        break;
                    }
                    tmp[ss]-=1;
                }
                if(j==i+wl*ll) res.push_back(i);
            }
            
            return res;   
    }
};




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值