枚举
概念
把可能的答案一个一个地列出来。
本质
所谓,暴力解法。列举、循环。
第一次错误提交:
bool containsPattern(vector<int>& arr, int m, int k) {
// 以每一个数为开头,试试
bool flag = false;
for (int i = 0; i < arr.size() - m + 1; i++) {
int cnt = 1, j = i; // 比较模式的第几个数
flag = true;
while (cnt <= k && j < arr.size() - m + 1) {
if (arr[j] == arr[j + m - 1]) {
j = j + m - 1;
cnt++;
} else {
flag = false;
break;
}
}
if (flag)
return true;
}
return false;
}
输入:
arr =[2,2,2,2]
m =2
k =3
输出:
true
预期结果
false
错误分析:
重复k次要比较k-1次。只比较了模式的第一个数字。——while (cnt <= k && j ……- 这里用for循环比较清晰,for和while混合用似乎会导致混乱。
第n次错误提交:
bool containsPattern(vector<int>& arr, int m, int k) {
4 // 边界条件:数组长度不足 m*k,直接返回false
5 if (arr.size() < m * k)
6 return false;
7 // 以每一个数为开头,试试
8 bool flag = true;
9 for (int i = 0; i <= arr.size() - m * k; i++) // 不重叠,找正确的模式开头
10 {
11 bool flag = false;
12 int cnt = 0; // 重复次数
13 // 一个模式,共有m个整数
14 for(int j = 0; j < m; j++) {
15 for(cnt=1; cnt<=k-1;cnt++){
16 if(arr[i+j]==arr[i+j+m*cnt]){
17 flag=true;
18 }else{
19 flag=false;
20 break;
21 }
22 }
23 if(!flag)
24 break;
25 }
26 if(!flag)
27 {
28 continue;
29 }else{
30 return true;
31 }
32 }
33 return flag;
34 }
错误分析:
范围边界设置错误——arr[i]始终是这个模式的开头,所以,范围是<=arr.size()-m*k。【为什么是等于?】如果模式的开头就是arr的开头arr[0]。
循环变量意义不明确——i表示当前模式的开头元素在arr数组内的下标,j表示元素在当前“模式”(以arr[i]为开头的)的第几个位置,cnt表示已经遍历的第几个重复的元素。
循环变量意义不明确——j是表示当前模式的第几个位置。
返回值的初始化——模式标志flag默认true,最后返回值是false,因为前面的循环后若是true一定会返回true。若出循环后,没有为true,或许是i取值的问题,或许是内部循环……
我的正确解法:
bool containsPattern(vector<int>& arr, int m, int k) {
// 边界条件:数组长度不足 m*k,直接返回false
if (arr.size() < m * k)
return false;
// 以每一个数为开头,试试
bool flag = true;
for (int i = 0; i <= arr.size() - m * k;
i++) // 不重叠,找正确的模式开头
{
bool flag = true;
int cnt = 0; // 重复次数
// 一个模式,共有m个整数
for (int j = 0; j < m; j++) {
for (cnt = 1; cnt <= k - 1; cnt++) {
if (arr[i + j] == arr[i + j + m * cnt]) {
flag = true;
} else {
flag = false;
break;
}
}
if (!flag)
break;
}
if (!flag) {
continue;
} else {
return true;
}
}
return false;
}
官方题解:
bool containsPattern(vector<int>& arr, int m, int k) {
int n = arr.size();
for (int l = 0; l <= n - m * k; ++l) //都是先遍历这个数组。
//高手原来都用++i
{
int offset;
//没有设置标志位。
//offset是模式的元素计数器。
for (offset = 0; offset < m * k; ++offset) {
if (arr[l + offset] != arr[l + offset % m]) {
//挨个和第一组m个比
break;
}
}
if (offset == m * k) {
return true;
}
}
return false;
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/detect-pattern-of-length-m-repeated-k-or-more-times/solutions/441150/zhong-fu-zhi-shao-k-ci-qie-chang-du-wei-m-de-mo-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
反思
- 做这一道题,耗费太长时间。当然,如果一鼓作气做下来的话,肯定没有这么长时间。一鼓作气!
- 【初始化】循环变量的初始化、返回值的初始化。
- 【变量的意义】定义这个变量来做什么。
- 【边界条件】可用特殊情况检验。
- 【循环的终止和继续】在哪continue,在哪break。
- 【返回值】考虑到剩余情况和特殊情况。