做题回顾

在过去的两周,看了大概30道算法题,实际上自己动手编码完成的有10道左右,使用的语言为C++。相关题目如下:

还包含在王道书籍上面的几道题目,总体而言。题目的难度不是很大,看完题目之后都有思路,但是在细节方面总是掌握不好。经常就是能很快确认思路,但是一旦编码总是不能尽快通过,存在各种各样逻辑问题和编码问题。在做题的时候遇到的困难如下:

  1. 思路难以确定
  2. 思路存在问题,等到编码调试的时候才发现,比较让费时间
  3. 思路没有问题,但是将思路转化成具体的算法存在问题,在进行编码的时候在细节方面处理的不是很好

做题总结

确定算法思想

首先要知道常见的算法思想例如:蛮力法,贪心策略,动态规划,递归和分治,排序+查找,快排分区。

同时还要掌握常见的数据结构,从简单到复杂依次为:数组,链表,栈和队列,二叉树,平衡二叉树,(红黑树,B树,B+树了解计科),图论算法。其中最难的就是图论算法。后面需要花一点时间在图论上面。

什么时候使用蛮力法

在使用蛮力法之前一定要估算问题复杂度。下面是昨天晚上做的一道题目,可能存在更好的解法,但是也可以通过蛮力法进行解决。

Shortest Uncommon Substring in an Array - LeetCode Contest

题目大意:给定一个字符串数组arr,长度为n。现在需要生成一个字符串数组answers。且answers满足如下的条件:

answers[i]中保存的值是arr[i]的子串,且arr除arr[i]以外的其他字符串皆不包含该子串。若这样的子串有多个,则选择长度最短的子串;若他们长度相同,则按字典序排序,选择字典序最小的子串;如果没有这样的子串,则返回空。

算法限制

  • n == arr.length
  • 2 <= n <= 100
  • 1 <= arr[i].length <= 20
  • arr[i] consists only of lowercase English letters.

下面包含两个例子:

Input: arr = ["cab","ad","bad","c"]
Output: ["ab","","ba",""]
Explanation: We have the following:
- For the string "cab", the shortest substring that does not occur in any other string is either "ca" or "ab", we choose the lexicographically smaller substring, which is "ab".
- For the string "ad", there is no substring that does not occur in any other string.
- For the string "bad", the shortest substring that does not occur in any other string is "ba".
- For the string "c", there is no substring that does not occur in any other string.

Example 2:

Input: arr = ["abc","bcd","abcd"]
Output: ["","","abcd"]
Explanation: We have the following:
- For the string "abc", there is no substring that does not occur in any other string.
- For the string "bcd", there is no substring that does not occur in any other string.
- For the string "abcd", the shortest substring that does not occur in any other string is "abcd".

思路分析:

在此之前,在看到一道算法题的时候,总是第一反应去想什么“巧”方法,但是在这个题目中实在是想不到,观察题目给出的限制,发现使用蛮力法的时候,复杂度也不是很大,算法思想为:

遍历一遍array数组,对于每一个元素array[i],求出array[i]的所有的子串,对于每一个子串sub,进行如下的处理:在array中除array[i]元素以外查找sub,如果都没有找到sub,说明sub符合题意。如果array[i]有多个子串满足题意,此时按照题目要求选择最短的。

考察算法最差情况下时间复杂度时先考察最基本语句也就是“在array中除array[i]元素以外查找sub”的执行次数最多为:

\[\frac{n.max^2.n}{2}\\ 其中n为array的长度,max为array数组元素的长度最大值。 \]

其中n=100,max=20则上面式子计算出来的值大概为1_000_000,大概100万次左右,其中查找操作调用C++里面提供的find函数,其实现基于KMP,执行次数最多为n+max也就是120次。最后得到完整的执行次数为1_2000_0000也就是1亿两千万次。看起来很多,但实际上由于每次都是执行最简单的比较查找操作,实际上代码运行时间也还可以接收。

完整代码如下:

class Solution
{
public:
    vector<string> shortestSubstrings(vector<string> &arr)
    {
        // 使用蛮力法
        vector<string> answer;

        for (int i = 0; i < arr.size(); i++)
        {
            string current = arr[i];
            string result = "";
            for (int j = 0; j < current.length(); j++)
            {
                for (int k = 0; j+k < current.length(); k++)
                {
                    // 获得子串
                    string sub = current.substr(j,k+1);

                    // 在其他子串中查找
                    int flag = 0;
                    for (int m = 0; m < arr.size(); m++)
                    {
                        if(m==i)continue;
                        if (arr[m].find(sub) != string::npos)
                        {
                            // 在其他字符串中找到此时sub不满足条件
                            flag = 1;
                            break;
                        }
                    }
                    if (flag == 0)
                    {   // 找到之后按照字典序进行比较,优先选择小的
                        if (result == "")
                            result = sub;
                        else
                        {
                            if(result.length()>sub.length()){
                                result = sub;
                            }else if(result.length()==sub.length()){
                                result = result.compare(sub) < 0 ? result : sub;
                            }
                        }
                    }
                }
            }
            answer.push_back(result);
        }
        return answer;
    }
};

最终代码运行的平均时间为400ms左右也算是比较慢的。而算法占用的空间就很小。

确定算法

编码

代码调试

题后总结

核心技巧总结

未来展望

C++二维数组赋值的几种方式

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int count(int (*p)[2], int m)
{

    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < 2; j++)
        {
            printf("%d ", p[i][j]);
        }
    }
    printf("\n");
}

int count(int **array, int m, int n)
{

    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            // printf("%d ", array[i][j]);

            printf("%d ", *((int *)array + i * n + j));
        }
    }
    printf("\n");
}

int count(int *array, int m, int n)
{
    for (int i = 0; i < m; i++)
    {
        for (int j = 0; j < n; j++)
        {
            printf("%d ", *(array + i * n + j));
        }
    }
}

int main()
{

    int array[3][2] = {1, 2, 3, 4, 5, 6};
    count((int **)array, 3, 2);
    count(array, 3);
    count((int *)array, 3, 2);
}
posted on 2024-03-15 17:29  劈瓜者刘华强  阅读(0)  评论(0编辑  收藏  举报