leetcode-72

题面

image-20201223212559309

官方题解

https://leetcode-cn.com/problems/minimum-window-substring/solution/zui-xiao-fu-gai-zi-chuan-by-leetcode-solution/

重点

  • 首先需要看懂官方题解,用滑动数组的方法,设置左指针left(0)和右指针right(-1),先让右指针增大,等到满足某一要求时,再让左指针增大,最后返回最小的窗口。

  • 右指针right为什么要从-1开始?

    因为每次进入循环时,right都会加1,如果right从0开始,就会漏掉第0个元素,参考队列(queue)数据结构,队尾指针也是从-1开始。

  • 如果按照官方题解的思想,然后自己写代码,需要经历三个阶段:

    1. 逻辑完全正确,只有最后一个测试用例超时。
    2. 逻辑完全正确,删去了很多无用的操作,把if-else的判断降低到最少,还是最后一个测试用例超时。
    3. 逻辑完全正确,采用官方题解中map的非理性写法,居然通过了。
  • map非理性写法:

    需求:“将mp中key对应的value加1”

    非理性写法:mp[key]++

    非理性之处:不去判断mp中是否有key对应的键值对,上来就用自增运算符。

  • 非理性写法通过的理由:

    1. 如果每次都判断mp中是否有key对应的键值对,需要使用find函数,find函数的时间复杂度为O(logN),N为mp中元素的个数,而随着mp规模的增大,将会耗费大量时间,

    2. mp[key]++,如果mp中没有key对应的键值对,那么它会自动创建一个键值对,默认value值为0

    3. 实验代码:

      #include <iostream>
      #include <stdio.h>
      #include <map>
      
      using namespace std;
      
      int main()
      {
          map<int,int> exp;
          for(int i=1; i<=10; i++){
              exp[i]++;
          }
          printf("key value\n");
          for(map<int,int>::iterator it=exp.begin(); it!=exp.end(); it++){
              printf("%d  %d\n",it->first,it->second);
          }
          return 0;
      }
      
      
image-20201223214619799
 ```c++
 #include <iostream>
 #include <map>
 
 using namespace std;
 
 int main()
 {
     map<int,int> exp;
     for(int i=1; i<=10; i++){
         exp[i];
     }
     printf("key value\n");
     for(map<int,int>::iterator it=exp.begin(); it!=exp.end(); it++){
         printf("%d  %d\n",it->first,it->second);
     }
     return 0;
 }
 
 ```
image-20201223214728048

源代码

理性写法(FA)

//思想上和官方题解一模一样,但就是超时
class Solution
{
public:
    map<char,int> tm;
    map<char,int> sm;
    bool check()
    {
        for(map<char,int>::iterator it = tm.begin(); it!=tm.end(); it++)
        {
            if(sm.find(it->first)!=sm.end())
            {
                if(sm[it->first]<it->second)
                {
                    return false;
                }
            }
            else{
                return false;
            }

        }
        return true;
    }

    string minWindow(string s, string t)
    {
        int tLen = t.size();
        int sLen = s.size();
        for(int i=0; i<tLen; i++)
        {
            if(tm.find(t[i]) == tm.end())
            {
                tm[t[i]] = 1;
            }
            else
            {
                tm[t[i]]++;
            }
        }
        int left = 0;
        int right = -1;
        int smallestLen = INT_MAX;
        int smallestLeft = -1;
        bool never = true;
        while(right<sLen)
        {
            right++;
            if(tm.find(s[right])!=tm.end())
            {
                if(sm.find(s[right]) == sm.end())
                {
                    sm[s[right]] = 1;
                }
                else
                {
                    int a = sm[s[right]];
                    sm[s[right]] = a + 1;
                }
            }
            //开始考虑向右移动左指针
            while(check() && left<=right)
            {
                if(right-left+1<smallestLen)
                {
                    smallestLen = right-left+1;
                    smallestLeft = left;
                }
                if(tm.find(s[left])!=tm.end()){
                    sm[s[left]]--;
                }
                //left++可能会导致check(tm,sm)函数返回false,此时会继续扩展right
                left++;
            }
        }

        if(smallestLeft == -1)
        {
            return "";
        }
        else
        {
            return s.substr(smallestLeft,smallestLen);
        }

    }
};

非理性写法(AC):

//采用非理性写法
class Solution
{
public:
    map<char,int> tm;
    map<char,int> sm;
    bool check()
    {
        for(map<char,int>::iterator it = tm.begin(); it!=tm.end(); it++)
        {
//            if(sm.find(it->first)!=sm.end())
//            {
//                if(sm[it->first]<it->second)
//                {
//                    return false;
//                }
//            }
//            else{
//                return false;
//            }
            //非理性之一 
            if(sm[it->first]<it->second){
                return false;
             }

        }
        return true;
    }

    string minWindow(string s, string t)
    {
        int tLen = t.size();
        int sLen = s.size();
        for(int i=0; i<tLen; i++)
        {
            tm[t[i]]++;
        }
        int left = 0;
        int right = -1;
        int smallestLen = INT_MAX;
        int smallestLeft = -1;
        bool never = true;
        while(right<sLen)
        {
            right++;
            if(tm.find(s[right])!=tm.end())
            {
                //非理性之二
                sm[s[right]]++;
            }
            //开始考虑向右移动左指针
            while(check() && left<=right)
            {
                if(right-left+1<smallestLen)
                {
                    smallestLen = right-left+1;
                    smallestLeft = left;
                }
                if(tm.find(s[left])!=tm.end()){
                    //非理性之三
                    sm[s[left]]--;
                }
                //left++可能会导致check(tm,sm)函数返回false,此时会继续扩展right
                left++;
            }
        }

        if(smallestLeft == -1)
        {
            return "";
        }
        else
        {
            return s.substr(smallestLeft,smallestLen);
        }
    }
};




posted on 2021-12-17 20:09  coderabcd  阅读(50)  评论(0)    收藏  举报

导航