算法-滑动窗口

一、知识点介绍

1. 滑动窗口的概念:

滑动窗口算法可以用以解决数组/字符串的子元素问题,它可以将嵌套的循环问题,转换为单循环问题,降低时间复杂度。

二、练习题目

        (1)1984. 学生分数的最小差值
        (2)1763. 最长的美好子字符串
        (3)2269. 找到一个数字的 K 美丽值

三、算法思路

1. 学生分数的最小差值

        (1)先要对数据进行预处理,对nums进行升序排序;
        (2)两个指针设置l为0, r为-1,一开始r向右滑动;
        (3)当窗口的大小大于k的时候,i也向右滑动;
        (4)每次都对比得出最小值就是答案。

class Solution {
public:
    int minimumDifference(vector<int>& nums, int k) {
        int l = 0;
        int r = -1;
        sort(nums.begin(), nums.end());
        int n = nums.size();
        int ans = 100010;
        while(r < n-1) {
            ++r;
            while(r-l+1 > k) {
                ++l;
            }
            if(r-l+1 == k) {
                ans = min(ans, nums[r] - nums[l]);
            }
        }
        return ans;
    }
};

2.最长的美好子字符串

        (1)这道题跟第一题类似,唯一的不同就是k的区间是不确定的,所以要遍历k的区间大小。在这道题里面设l为区间大小,因题意要获得最长的美好子字符串,所以l的区间大小要从大到小遍历;
        (2)用一个哈希表存储所有字母的个数;
        (2)跟第一题类似,当发现美好子字符串的时候直接返回。

class Solution {
    int code(char c) {
        if(c >= 'a' && c <= 'z') {
            return c - 'a';
        }
        return c - 'A' + 26;
    }
public:
    string longestNiceSubstring(string s) {
        int l, i, j, k;
        int n = s.size();
        int hash[52];
        for(l = n; l > 0; --l) {
            i = 0;
            j = -1;
            memset(hash, 0, sizeof(hash));
            while(j < n - 1) {
                ++j;
                ++hash[code(s[j])];
                while(j-i+1 > l) {
                    --hash[code(s[i])];
                    ++i;
                }
                if(j-i+1 == l) {
                    for(k = 0; k < 26; ++k) {
                        if(hash[k] && !hash[k+26]) break;
                        if(!hash[k] && hash[k+26]) break;
                    }
                    if(k == 26) {
                        return s.substr(i, j-i+1);
                    }
                }
            }
        }
        return "";
    }
};

3. 找到一个数字的 K 美丽值

        (1) 先要把数字的每一位存入数组当中;
        (2) 类似于第一题,滑动窗口,判断每一次的值是不是可以整除自己本身,可以就答案+1.

class Solution {
public:
    int divisorSubstrings(int num, int k) {
     vector<int> stk;
     int f[10];
     f[0] = 1;
     for(int i = 1; i < 10; ++i) {
         f[i] = f[i-1] * 10;
     }
     int N = num;
     int ans = 0;
     while(num) {
         stk.push_back(num%10);
         num /= 10;
     }
     reverse(stk.begin(), stk.end());
     int i = 0, j = -1;
     int sum = 0;
     int size = stk.size();
     while(j < size -1) {
         ++j;
         sum = sum*10 + stk[j];
         while(j-i+1 > k) {
             ++i;
             sum %= f[k];
         }
         if(j-i+1 == k) {
             if(sum && N % sum == 0) {
                 ++ans;
             }
         }
     }
     return ans;
    }
};

四. 总结

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值