प्रौद्योगिकी साझेदारी

【leetcode】स्लाइडिंग विण्डो विषय

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

1. न्यूनतमदीर्घतायाः सह उपसरणिका

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
leetcode 209. न्यूनतमदीर्घतायाः सह उपसरणिका

एतत् विषयं दृष्ट्वा प्रथमं मनसि हिंसकगणना एव आगच्छति अतः निम्नलिखितगणनां प्रयत्नः करणीयः ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

स्पष्टतया, क्रूरबलगणनाविधिः समयं समाप्तं करिष्यति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

अतः किं तस्य अनुकूलनस्य कोऽपि उपायः अस्ति यत् तस्य समयः न समाप्तः भवति? तस्य विश्लेषणं कुर्मः : १.

हिंसकगणनायां अस्माकं दक्षिणः प्रतिवारं वामस्य अग्रिमस्थानं प्रति आगमिष्यति, ततः वामभागेन सह पुनः गणनां करिष्यति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
गणनायाः अनुकूलनार्थं विशिष्टानि पदानि निम्नलिखितरूपेण सन्ति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

उपरिष्टाद् गणनाप्रक्रियायां अस्माकं नीलवर्णीयपेटी अनिर्धारितप्रमाणेन सह स्लाइडिंग् विण्डो इव अस्ति वयम् एतत् पद्धतिं वदामःस्लाइडिंग् विण्डो

स्लाइडिंग् विण्डो इत्यस्य कृते निम्नलिखितपदार्थेभ्यः अधिकं किमपि नास्ति ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
प्रत्येकस्य प्रश्नविण्डो इत्यस्य आरम्भबिन्दुः अद्यतनपरिणामानां स्थानं च न निश्चितं भवति, विशिष्टस्थितिः च प्रकरण-प्रकरण-आधारेण विश्लेषिता भविष्यति

स्लाइडिंग् विण्डो मेथड् इत्यस्य अनुसारं अस्माकं कोड् टाइम आउट् न भविष्यति ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
संक्षेपेण निम्नलिखितकालजटिलतायाः विश्लेषणं कुर्वन्तु: कोडात् O(n2), परन्तु अस्माकं स्लाइडिंग् विण्डो विचारस्य कारणात्, द्वौ सूचकौ समानदिशि भ्रमन्ति तथा च यदा सम्यक् सूचकः समाप्तः भवति तदा लूप् समाप्तः भवति, अतः तस्यकालजटिलता ओ(न) भवति।

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int ret = INT_MAX;
        int n = nums.size();
        int sum = 0;
        for(int left = 0, right = 0; right < n; right++)//right后移
        {
            //进窗口
            sum += nums[right];
            //判断窗口
            while(sum >= target)
            {
                //符合条件,更新结果
                ret = min(ret,right - left + 1);
                sum -= nums[left];//出窗口
                left++;
            }  
        }
        if(ret == INT_MAX)
            return 0;
        else
            return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

2. पुनरावृत्तिवर्णरहितः दीर्घतमः उपतारः

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
leetcode 3. पुनरावृत्तिवर्णरहितं दीर्घतमं तारम्

अस्य प्रश्नस्य कृते प्रथमः विधिः यः मनसि आगच्छति सः निःसंदेहं गणना अस्ति, ततः प्रत्येकं वर्णं कियत्वारं दृश्यते इति गणना यदि कश्चन वर्णः द्विवारं दृश्यते तर्हि वर्तमानवर्णस्य अनुरूपं तारं दीर्घतमं उपतारं भवति
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
वयं ज्ञातवन्तः यत् brute force enumeration method अपि उत्तीर्णं कर्तुं शक्नोति
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

किं तस्मात् उत्तमः समाधानः अस्ति ?तस्य विश्लेषणं कुर्मः
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
उपर्युक्तं समाधानं केवलं स्खलितं खिडकं न भवति वा ?
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

किं अस्मिन् समये कालजटिलता O(n) हिंसकगणना O(n) इत्यस्मात् श्रेष्ठा अस्ति?2) इत्यपि श्रेष्ठम्

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int n = s.size();
        int hash[128] = { 0 };
        int ret = 0;
        for(int left = 0, right = 0; right < n; right++)
        {
            hash[s[right]]++;//入窗口,先记录当前
            while(hash[s[right]] > 1)//若s[right]重复
            {
                hash[s[left]]--;//出窗口
                left++;
            }
            ret = max(ret,right - left + 1);//更新结果
        }
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

3. अधिकतमं क्रमशः 1’s III

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
leetcode 1004. अधिकतम संख्या क्रमशः 1's III

विषयस्य विश्लेषणं कृत्वा वयं तत् द्रष्टुं शक्नुमः0 प्लवितुं शक्यते इति तथ्यस्य अर्थः अस्ति यत् 0 1 इति रूपेण उपयोक्तुं शक्यते . ततः अस्माकं लक्ष्यं अस्ति यत् एकं अन्तरालं अन्वेष्टुम् यस्मिन् 1 इत्यस्य बृहत्तमसंख्या भवति, अस्मिन् अन्तरालस्य 0 इत्यस्य संख्या k इत्यस्मात् अधिकं न भवितुम् अर्हति ।

अस्य प्रश्नस्य हिंसकगणनाविधिः न प्रदर्शिता भविष्यति ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
एवं अस्माकं कोडः उत्तीर्णः भविष्यति
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

class Solution {
public:
    int longestOnes(vector<int>& nums, int k) {
        int n = nums.size();
        int zero = 0;//统计0的个数
        int ret = 0;
        for(int left = 0, right = 0; right < n; right++)
        {
            //进窗口,判断是否是0
            if(nums[right] == 0)
                zero++;
            //判断0的个数是否大于k
            while(zero > k)
            {
                //判断是否是0出窗口
                if(nums[left] == 0)
                    zero--;
                left++;
            }
            //更新结果
            ret = max(ret,right-left+1);
        }
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

4. x 0 यावत् न्यूनीकर्तुं न्यूनतमं क्रियाणां संख्या

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
leetcode 1658. x 0 पर्यन्तं न्यूनीकर्तुं न्यूनतमं कार्यसङ्ख्या

प्रश्नान् पठित्वा वयं ज्ञातुं शक्नुमः यत् एतत् वामभागे दक्षिणभागे च अस्ति तर्हि तस्य नियन्त्रणं कठिनम् अस्ति वा?
कठिने सति विपरीतम्

  • वयं सरणीयां निरन्तरं अन्तरालं प्राप्नुमः, सरणीयां निरन्तरस्य अन्तरालस्य सामग्रीं निष्कासयामः, अवशिष्टा सामग्री च x इत्यस्य समीचीनतया समाना भवति, तर्हि किं वयं स्थितिं प्राप्तवन्तः?
  • अयं निरन्तरः अन्तरालः अस्तिसरणी माइनस x मध्ये तत्त्वानां योगः
  • यदा सरणीयां दीर्घतमः निरन्तरः अन्तरालः लभ्यते तदा अस्माभिः सर्वोत्तमः समाधानः प्राप्तः ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
अद्यापि पूर्वप्रश्नस्य इव स्लाइडिंग् विण्डो इत्यस्य उपयोगं कुर्वन्तु ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

class Solution {
public:
    int minOperations(vector<int>& nums, int x) {
        int ret = 0;
        int total = 0;
        int n = nums.size();
        for(auto e : nums)
            total += e; //求数组的和
        int target = total - x; //target为要找的连续区间的总大小

        if(target < 0)//细节
            return -1;
        if(total == x)
            return n;
            
        int sum = 0;
        for(int left = 0, right = 0; right < n; right++)
        {
            sum += nums[right];//进窗口
            while(sum > target)
            {
                sum -= nums[left];
                left++;
            }
            if(sum == target)//找到目标区间,取长的一个
                ret = max(ret,right - left + 1);
        }
        if(ret == 0)
            return -1;
        else
            return n - ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

5. फलानां टोपलाः

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
leetcode 904.टोकरीयां फलानि

एतत् उपाधिं तावत् दीर्घम् अस्ति, तस्य अर्थः किम् ?

केवलं द्वौ टोपलौ स्तः, टोपले केवलं द्विविधं फलं भवितुम् अर्हति, ते च वृक्षान् लङ्घयितुं न शक्नुवन्ति ।
सः निरन्तरस्य अन्तरालस्य दीर्घतां अन्वेष्टुं वयं स्लाइडिंग् विण्डो इत्यस्य उपयोगं कर्तुं शक्नुमः

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
अतः कथं ज्ञास्यामि यत् सम्प्रति कति फलानि उद्धृतानि सन्ति ? ----हैश टेबल आँकडानां उपयोगं कुर्वन्तु
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
वयं ज्ञातुं शक्नुमः यत् हैश टेबल् इत्यस्य उपयोगस्य उपभोगः अद्यापि अत्यन्तं विशालः अस्ति किं तत् अधिकं अनुकूलितं कर्तुं शक्यते?

प्रश्नापेक्षाभ्यः द्रष्टुं शक्यते यत् वर्गः १० तः न्यूनः अस्ति5, अतः वयं प्रत्यक्षतया एकं array + एकं चर (record type) उपयोक्तुं शक्नुमः ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

एवं प्रकारेण अस्माकं कार्यक्षमतायाः बहु उन्नतिः अभवत् ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        int n = fruits.size();
        int ret = 0;
        int hash[100000] = { 0 };
        int kinds = 0;
        for(int left = 0, right = 0; right < n; right++)
        {
            if(hash[fruits[right]] == 0)//判断是否是新种类水果
                kinds++;

            hash[fruits[right]]++;//进窗口
            
            while(kinds > 2)//判断总类是否大于2
            {
                hash[fruits[left]]--;//出窗口
                if(hash[fruits[left]] == 0)
                    kinds--;  //去除该种类
                left++;
            }
            ret = max(ret,right - left + 1);
        }
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

6. स्ट्रिंग् मध्ये सर्वाणि अक्षर-अनाग्रामाणि अन्वेष्टुम्

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

leetcode 438. एकस्मिन् स्ट्रिंग् मध्ये सर्वाणि अक्षर-अनाग्रामाणि ज्ञातव्यम्

प्रश्नस्य विश्लेषणात् वयं द्रष्टुं शक्नुमः यत् s स्ट्रिंग् मध्ये p स्ट्रिंग् अन्वेष्टुम् अस्ति (p स्ट्रिंग् मध्ये वर्णानाम् क्रमः बाधितः भवितुम् अर्हति) ।
तदा वयं शक्नुमःकेवलं एकं उपस्ट्रिंग् अन्वेष्टुम् यस्य दीर्घता p इत्यस्य समाना भवति, यस्य वर्णप्रकारः संख्या च p स्ट्रिंग् इत्यस्य बराबरम् अस्ति ।

अतः वयं क्रमशः p तथा string s इत्यस्मिन् वर्णानाम् प्रकारान् संख्यां च गणयितुं द्वौ hash tables उपयोक्तुं शक्नुमः ।

ततः प्रथमं हिंसकगणनायाः उपयोगेन तस्य प्रयासं कुर्मः :
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

द्वयोः हैश-सारणीयोः तुलना कथं भवति ?

  1. प्रथमं p स्ट्रिंग् मध्ये वर्णप्रकारस्य संख्यां अभिलेखयितुं hash1 इत्यस्य उपयोगं कुर्वन्तु ।
  2. s भ्रमित्वा उपस्ट्रिंग् अन्वेष्टुम् यस्य दीर्घता p इत्यस्य बराबरम् अस्ति, तथा च hash2 वर्तमानवर्णं संग्रहयति ।
    a. यदि hash2[right] &lt;= hash1[right] तर्हि "वैधवर्णानां" प्रकाराः वर्धन्ते
    ख. यदि hash2[right] &gt; hash2[right] तर्हि "वैधवर्णानां" प्रकारः अपरिवर्तितः एव तिष्ठति

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
हिंसकगणनाविधिः खलु सम्भवः, परन्तु सा तुल्यकालिकरूपेण अकुशलः अस्ति ।
यतः वयं निरन्तरं अन्तरालं अन्विष्यामः, किं वयं स्लाइडिंग् विण्डो इत्यस्य उपयोगं कर्तुं शक्नुमः?प्रयासं कुर्मः
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
एवं अस्माकं कार्यक्षमता बहु अधिका भविष्यति
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

class Solution {
public:
    vector<int> findAnagrams(string s, string p) {
        vector<int> ret;
        int len = p.size();
        int hash1[128] = { 0 };
        for(auto e: p)
            hash1[e]++;//统计p串的种类
        int n = s.size();
        int hash2[128] = { 0 };//统计子串种类
        int kinds = 0;
        int tmp = 0;
        for(int left = 0,right = 0; right < n ; right++)
        {
            hash2[s[right]]++; //进窗口
            tmp++;//子串长度增加
            if(hash2[s[right]] <= hash1[s[right]])
                kinds++;//"有效字符"种类增加
            if(tmp > len)
            {
                if(hash2[s[left]] <= hash1[s[left]])
                    kinds--;//left位置为“有效字符”,种类减少
                hash2[s[left]]--;
                tmp--;
                left++;
            }
            if(tmp == len)
                if(kinds == len)
                    ret.push_back(left);
        }
        return ret;
        
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

7. सर्वेषां शब्दानां उपतारं संयोजयन्तु

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

leetcode 30. सर्वेषां शब्दानां उपतारं संयोजयन्तु

अयं प्रश्नः पूर्वप्रश्नस्य सदृशः अस्ति, केवलं वर्णानाम् स्थाने ताराः भवन्ति इति व्यतिरिक्तम् । अतः वयं अद्यापि समस्यायाः समाधानार्थं: sliding window + hash table इत्यस्य उपयोगं कुर्मः ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

समस्यानिराकरणपदार्थाः : १.

  1. प्रथमं शब्देषु स्ट्रिंग्-प्रकारस्य गणनाय hash1 इत्यस्य उपयोगं कुर्वन्तु
  2. स्लाइडिंग् विण्डो इत्यस्य उपयोगं कुर्वन्तु (यतोहि तारस्य दीर्घता नियतं भवति, अतः भवन्तः प्रत्यक्षतया दीर्घतां कूर्दितुं शक्नुवन्ति)
    क. परिभाषा आरम्भः वाम, दक्षिण
    b. यदा स्ट्रिंग् विण्डो मध्ये प्रविशति तदा भवद्भिः तत् कटयितुं स्ट्रिंग् फंक्शन् substr इत्यस्य उपयोगः करणीयः ।
    ग. तारस्य प्रकारं निर्धारयतु
    खिडकीतः निर्गन्तुं वा
    परिणामान् अद्यतनं कुर्वन्तु

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
परन्तु कोडस्य भागः एव उत्तीर्णः अभवत् तस्य परीक्षणप्रकरणानाम् विश्लेषणेन ज्ञातं यत्, ।
अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
एषः एव संहिता !

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ret;
        unordered_map<string,int> hash1;
        for(auto& e : words)
            hash1[e]++;//统计要求的字符串种类
        int n = s.size();
        int len = words[0].size();//固定的字符串长度
        int m = words.size();//数组长度
        for(int i=0; i < len; i++)
        {
            unordered_map<string,int> hash2;
            int count = 0;
            for(int left = i, right = i; right <= n -len; right+= len)
            {
                string in = s.substr(right,len);//裁剪字符串
                hash2[in]++;//进窗口
                if(hash2[in] <= hash1[in])
                    count++;//统计当前字符串数量
                if(right - left + 1 > m*len)//判断字符串数量是否大于字符数组
                {
                    string out = s.substr(left,len);
                    if(hash2[out] <= hash1[out])
                        count--;
                    hash2[out]--;//出窗口
                    left += len;
                }
                if(count == m)
                    ret.push_back(left);
            }
        }
        return ret;
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

8. न्यूनतमं कवरिंग् उपस्ट्रिंग्

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु
leetcode 76. न्यूनतमं कवरिंग् उपस्ट्रिंग्

अस्य प्रश्नस्य समाधानं पूर्वप्रश्नस्य सदृशं भवति यत् एतत् स्ट्रिंग् s इत्यस्य सर्वाणि वर्णाः अपि अन्वेषयति, केवलं प्राप्तानां स्ट्रिंग्-मध्ये लघुतमं वर्णं प्रत्यागच्छति ।

अद्यापि वयं तस्य समाधानार्थं sliding window + hash table इत्यस्य उपयोगं कुर्मः ।

  1. t स्ट्रिंग् मध्ये वर्णानाम् प्रकारं संख्यां च गणयितुं hash1 इत्यस्य उपयोगं कुर्वन्तु
  2. स्लाइडिंग् विण्डो: आरम्भस्थानं वाम, दक्षिणं परिभाषयन्तु
    क. विण्डो प्रविशतु
    ख. विण्डो दृश्यते वा इति निर्धारयतु
    ग. परिणामं अद्यतनं कुर्वन्तु (केवलं तारस्य आरम्भस्थानं दीर्घतां च अभिलेखयितुम् आवश्यकम्, अन्ते च उपतारं कटयन्तु)

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

केवलं कोड् मध्ये स्ट्रिंग् इत्यस्य आरम्भस्थानं दीर्घतां च अभिलेखयन्तु, अस्माकं कोड् समाप्तं भविष्यति ।

अत्र चित्रविवरणं सम्मिलितं कुर्वन्तु

class Solution {
public:
    string minWindow(string s, string t) {
        int hash1[128] = { 0 };
        for(auto e : t)
            hash1[e]++;//统计t串的字符种类和数量
        int m = t.size();
        int n = s.size();
        int hash2[128] = { 0 };
        int count = 0;
        int start = 0;
        int len = INT_MAX;
        for(int left = 0, right = 0; right < n; right++)
        {
            hash2[s[right]]++;//进窗口
            if(hash2[s[right]] <= hash1[s[right]])//是否更新有效字符
                count++;
            while(count >= m)//是否出窗口
            {
                if(count == m)//找到符合种类的子串
                {
                    //取长度小的一个
                    int curlen = right - left + 1;
                    if(curlen < len)
                    {
                        start = left;
                        len = curlen;
                    }
                }
                //出窗口
                if(hash2[s[left]] <= hash1[s[left]])
                    count--;
                hash2[s[left]]--;
                left++;
            }
        }
        if(len == INT_MAX)
            return "";
        else
            return s.substr(start,len);
    }
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42