week34

331 - 验证二叉树的前序序列化

递归遍历 是我学不会了

左右子树必须有东西(#也算)所以以这个作为遍历的基础 递归判断 只需从左到右遍历数组一次即可

注意的点:

  • , 作为元素分割的依据,所以要在最后补上一个逗号

  • 递归中发现元素遍历完——则存在一遍子树没有元素(结束#也没有)所以不合法

  • 最后 判断所有元素遍历完才合法 比如9, #, #, 1

class Solution {
public:
    bool ans = true;
public:
    bool isValidSerialization(string s) {
        int u = 0;
        s +=','; // 以逗号作为element分割依据
        dfs(s, u);
        return ans && u == s.size(); // 注意这里还要保证遍历完
    }
    void dfs(string& s, int& u)
    {
        if(u == s.size())
        {
            ans = false;
            return;
        }
        if(s[u] == '#')
        {
            u += 2;
            return;
        }
        while(s[u] != ',') u++;
        u++; // 过滤等号
        // 根 左 右
        dfs(s, u);
        dfs(s, u);
        return;
    }
};

332 - 重新安排行程

经典的欧拉回路问题;不重不漏的走所有边;

复习一下欧拉路径和欧拉回路

除了保证连通性之外

欧拉路径:

  • 无向图:度数为奇数的点只能有0个or2个 (起点和终点)

  • 有向图:所有点的入度=出度 要么除了两个点的入度=出度,且这两个点一个出度比入度大一,一个入度比出度大一(起点和终点)

欧拉回路:

  • 无向图:不能有度数为奇数的点

  • 有向图:所有点的入度等于出度

求欧拉回路/欧拉路径的方法:

DFS-在搜完这个点的所有邻接边之后,再将这个点加入答案序列,最终返回序列的逆序

一些细节:

  • 这里是用边来判重,所以用完了一条边就要删除(额外标记也行)

  • 无向图是建双向边的形式来实现的 但是用了一条要删除两条边,如何找反向边呢?双向边都是成对建的,所以i ^ 1即为对应的反向边

  • 最小字典序的方法就是搜的时候按照最小字典序来搜

334 - 递增的三元子序列

本题是最长上升子序列问题(LIS)问题的一个简化版相当于,找到长度为3的最长上升子序列;

对于LIS问题,有一个贪心的解法可以实现nlogn的时间复杂度,具体思路是用一个数组q[k] 表示长度为K的最长上升子序列中结尾的元素最小值

这样每次找到q中第一个比nums[i]大的值,并更新其为nums[i]就行了

这里的思路是把q直接用两个数表示 所以可以实现o(n)的时间复杂度

336 - 回文对

SOS 好多Hard

这题有两个做法 主要记住第二个

  1. 暴力+字符串哈希 (o(n^2l))

暴力思想很简单,枚举两个字符串,判断拼成的字串是不是回文子串,这里判断是否回文子串用字符串哈希来实现 不然会TLE

  1. o(nl^2)版本

337 - 打家劫舍III

经典的树形DP问题,返回值是选 or 不选 组成的一个pair

338 - 比特位计数

计算从1 - n 中, 每个数的二进制表示中1的个数

递推:对于每个数x的二进制表示中1的个数,可以通过 x >> 1 的个数 加上最后一位是否为1来实现;

Last updated