(纯C解决)滑动窗口算法经典例题--最小覆盖子串

题目:

在这里插入图片描述

纯C解决:

无非就是那几个步骤
1.构建判断是否符合条件的need表
2.构建跟随滑动窗口更新的window表
3.创建left和right用于滑动
4.根据滑动过程再适当的更新答案

只要耐心看完这个代码应该就能懂了


//【算法思路】滑窗+hash
//其实可以比喻left和right为窗口界定,而hash表中元素的增减操作,可以看作用于判断是否收缩窗口的工具,我亲切称其为橱柜。
char * minWindow(char * s, char * t){
    int need[128]={0};
    int window[128]={0};
    int hash_len = 0;
    //更新need橱柜
  for(int i=0;t[i]!='\0';i++){
      need[t[i]]++;
        if(need[t[i]]==1){
            //计算有多少个不同的字符(即哈希表的长度)
            hash_len++;
        }
  }
  int left=0,right=0;
  //vali用于记录达到有效值的字符数
  int valid=0;
  int start=0,len=INT_MAX;
  //开始滑动窗口
  while(s[right]!='\0'){
//滑入窗口的字符,把它用变量单独存储,是需要right能够灵活的变化位置,后面的left也是一样
//比如这里的right实际上是每次扫描进橱柜的后一个位置,这样可以保证用right-left更新len不用考虑right的值是否要变换。
      char c = s[right];
      right++;
      //右边扩大窗口
      if(need[c]){
          window[c]++;
          if(window[c]==need[c])
            valid++;
      }
      //当右边扩大到位后,开始收缩左窗口
      while(valid==hash_len){
            //更新最小覆盖子串
        if(right-left<len){
            start = left;
            len = right-left;
        }
        //收缩左窗口,确保left所指的位置正是移出橱柜后的状态
        char c = s[left];
        if(need[c]){
            window[c]--;
            if(window[c]<need[c])
            valid--;
        }
        left++;
      }
  }
  //当len未更新时则说明不存在,故return "",否则为q。
  char* q = s+start;
  if(len==INT_MAX)
    return "";
    q[len]='\0';
  return q;
}

C++解决:

唯一的区别就是比C多了很多的类和库
还有就是比C慢太多了。。当然也可以用数组作为hash表提高效率。这样和C的效率差距就不是很大了。

class Solution {
public:
    string minWindow(string s, string t) {
    unordered_map<char,int>need;
    unordered_map<char,int>window;
    for(char c:t)need[c]++;
    int left=0,right=0;int valid = 0;
    int len = INT_MAX;
    int start = 0;
    
    while(right<s.size()){
    char c = s[right];
        right++;
    //右移窗口操作
    if(need.count(c)){
        window[c]++;
        if(need[c]==window[c])
            valid++;
    }
    //左移窗口操作
    while(valid==need.size()){
    //更新数据,使得len取最小
    if(right-left<len){
    start = left;
    len = right-left;}
    //移出窗口操作
    char c = s[left];
    if(need.count(c)){
        window[c]--;
        if(window[c]<need[c])
            valid--;
    }
    left++;
    }
    }
    return len==INT_MAX?"":s.substr(start,len);
    
    }
};

滑动窗口的模板:

void slidingWindow(string s,string t){
	unordered_map<char,int>need,window;
	
	int left=0,right=0;
	int valid=0;
	while(right<s.size()){
	//c是要移入窗口的字符
	char c = s[right];
	//右移窗口
	right++;
	//进行窗口内数据的一系列更新
	...
	/*** debug输出的位置 ***/
	printf("window: [%d,%d]\n",left,right);
	/********************/
	
	//判断左窗口是否要收缩
	while(window needs shrink){
	//d是将移出窗口的字符
	char d = s[left];
	//收缩窗口
	left++;
	//进行窗口一系列数据的更新
	...
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值