一、知识点介绍
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;
}
};