枚举

22 阅读3分钟

枚举

概念

把可能的答案一个一个地列出来。

本质

所谓,暴力解法。列举、循环。

  1. 1566. 重复至少 K 次且长度为 M 的模式

第一次错误提交:

    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

错误分析:

  1. 重复k次要比较k-1次。
  2. 只比较了模式的第一个数字。——while (cnt <= k && j ……
  3. 这里用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    }

错误分析:

  1. 范围边界设置错误——arr[i]始终是这个模式的开头,所以,范围是<=arr.size()-m*k。

    【为什么是等于?】如果模式的开头就是arr的开头arr[0]。

  2. 循环变量意义不明确——i表示当前模式的开头元素在arr数组内的下标,j表示元素在当前“模式”(以arr[i]为开头的)的第几个位置,cnt表示已经遍历的第几个重复的元素。

  3. 循环变量意义不明确——j是表示当前模式的第几个位置。

  4. 返回值的初始化——模式标志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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

反思

  1. 做这一道题,耗费太长时间。当然,如果一鼓作气做下来的话,肯定没有这么长时间。一鼓作气!
  2. 【初始化】循环变量的初始化、返回值的初始化。
  3. 【变量的意义】定义这个变量来做什么。
  4. 【边界条件】可用特殊情况检验。
  5. 【循环的终止和继续】在哪continue,在哪break。
  6. 【返回值】考虑到剩余情况和特殊情况。