210场周赛

这次结果不是很好,总结了一下,还是关于图结构以及字符串类型的题目做的不是很多,对其的相关解法不是很熟悉,后续在这两方面加强一下。

5535. 括号的最大嵌套深度(EASY)

题目描述:如果字符串满足一下条件之一,则可以称之为 有效括号字符串(valid parentheses string,可以简写为 VPS):

字符串是一个空字符串 "",或者是一个不为 "(" 或 ")" 的单字符。
字符串可以写为 AB(A 与 B 字符串连接),其中 A 和 B 都是 有效括号字符串 。
字符串可以写为 (A),其中 A 是一个 有效括号字符串 。
类似地,可以定义任何有效括号字符串 S 的 嵌套深度 depth(S):

depth("") = 0
depth(A + B) = max(depth(A), depth(B)),其中 A 和 B 都是 有效括号字符串
depth("(" + A + ")") = 1 + depth(A),其中 A 是一个 有效括号字符串
例如:""、"()()"、"()(()())" 都是 有效括号字符串(嵌套深度分别为 0、1、2),而 ")(" 、"(()" 都不是 有效括号字符串 。

给你一个 有效括号字符串 s,返回该字符串的 s 嵌套深度 。

分析:和之前leetcode的判断括号有效性类似,而且比那个还要简单,因为本题只有一种类型的括号,而且肯定是成对出现的,直接上代码。

class Solution {
public:
    int maxDepth(string s) {
        int max_val = 0;
        int k = 0;
        unordered_map<char, char> strmap{ {')', '('}};
        stack<char> tempstack;
        for(int i=0;i<s.size();i++){
            if(s[i] == '('){
                tempstack.push(s[i]);
                k++;
                if(k>max_val)
                    max_val = k;
            }
            else if(tempstack.empty() || tempstack.top() != strmap[s[i]])
                continue;
            else{
                tempstack.pop();
                k--;
            }
        }
        return max_val;
    }
};

这里还可以简化一下的,不用栈和哈希表

class Solution {
public:
    int maxDepth(string s) {
        int max_val = 0;
        int k = 0;
        for(int i=0;i<s.size();i++){
            if(s[i] == '('){
                k++;
                if(k>max_val)
                    max_val = k;
            }
            else if(s[i] == ')'){
                k--;
            }
        }
        return max_val;
    }
};

5536. 最大网络秩(MEDIUM)

题目描述:n 座城市和一些连接这些城市的道路 roads 共同组成一个基础设施网络。每个 roads[i] = [ai, bi] 都表示在城市 ai 和 bi 之间有一条双向道路。

两座不同城市构成的 城市对 的 网络秩 定义为:与这两座城市 直接 相连的道路总数。如果存在一条道路直接连接这两座城市,则这条道路只计算 一次 。

整个基础设施网络的 最大网络秩 是所有不同城市对中的 最大网络秩 。

给你整数 n 和数组 roads,返回整个基础设施网络的 最大网络秩 。

分析:这道题我的思路是,先遍历求出每个节点的连接的边的个数,然后找出两个边大的节点,将他们的边数求和,如何这两个节点直接相连的化,再去重减一;理论上我觉得没有什么问题,但是中间还是出了问题。看了一下前排大佬的解法,发现还是自己像太复杂了,基本的思路是对的,就是将两个节点边数相加,但是我们不需要单独找边数最大的两个点,直接找最大边数和就行,抓住目标才对。

class Solution {
public:
    int maximalNetworkRank(int n, vector<vector<int>>& r) {
        vector<vector<int> > a(n, vector<int>(n, 0));
        for(auto & tmp : r) {
            a[tmp[0]][tmp[1]]++;
            a[tmp[1]][tmp[0]]++;
        }
        int mx = 0;
        for(int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) {
                if(i == j) continue;
                int cnt = 0;
                for(int k = 0; k < n; k++) {
                    if(k == i || k == j) continue;
                    if(a[i][k]) cnt++;
                    if(a[j][k]) cnt++;
                }
                if(a[i][j]) cnt++;
                mx = max(mx, cnt);
            }
        }
        return mx;
    }
};

5537. 分割两个字符串得到回文串(MEDIUM)

题目描述:给你两个字符串 a 和 b ,它们长度相同。请你选择一个下标,将两个字符串都在 相同的下标 分割开。由 a 可以得到两个字符串: aprefix 和 asuffix ,满足 a = aprefix + asuffix ,同理,由 b 可以得到两个字符串 bprefix 和 bsuffix ,满足 b = bprefix + bsuffix 。请你判断 aprefix + bsuffix 或者 bprefix + asuffix 能否构成回文串。

当你将一个字符串 s 分割成 sprefix 和 ssuffix 时, ssuffix 或者 sprefix 可以为空。比方说, s = "abc" 那么 "" + "abc" , "a" + "bc" , "ab" + "c" 和 "abc" + "" 都是合法分割。

如果 能构成回文字符串 ,那么请返回 true,否则返回 false 。

请注意, x + y 表示连接字符串 x 和 y 。

分析:这题比较简单的思路就是遍历每个位置,然后判断组合的字符串是否为回文串,但是带来的问题是容易超出时间限制。看了别人的解法后,发现可以不用一定要确定切分点的位置,可以先从总体上总的进行分析。如果A和B组合,两种情况:

  • A短B长,A在前段
    - 如果符合回文串,则前半段A[i]=B[n−i+1],后段B[i]=B[n−i+1]
  • A长B短,B在前段
    - 如果符合回文串,则前半段B[i]=A[n−i+1],后段A[i]=A[n−i+1]
    另外就是空串的情况,那么就是检查自身是否是回文串了。这里一个技巧就是,我只对A的前半段判断,那么就是第一种情况,但是B在后半段,所以这里直接判断第二种情况的A[i]=A[n−i+1],后面再调换A和B顺序,这样两种都能判断到;这里对A,B反序是为了判断后半段的情况,这样一个函数做四次判断,简洁效率。
class Solution {
    bool check(string a, string b) {
        int n = a.size();
        bool flag = true;
        for (int i = 0; i < n / 2; ++i) {
            if (flag) {
                if (a[i] != b[n - 1 - i])
                    flag = false;
            }
            if (!flag)
                if (a[i] != a[n - 1 - i])
                    return false;
        }
        return true;
    }
public:
    bool checkPalindromeFormation(string a, string b) {
        if (check(a, b) || check(b, a))
            return true;
        reverse(a.begin(), a.end());
        reverse(b.begin(), b.end());
        if (check(a, b) || check(b, a))
            return true;
        return false;
    }
};

作者:lucifer1004
链接:https://leetcode-cn.com/problems/split-two-strings-to-make-palindrome/solution/jiao-huan-dao-xu-wo-men-ju-jue-fen-qing-kuang-tao-/

5538. 统计子树中城市之间最大距离(HARD)

题目描述:给你 n 个城市,编号为从 1 到 n 。同时给你一个大小为 n-1 的数组 edges ,其中 edges[i] = [ui, vi] 表示城市 ui 和 vi 之间有一条双向边。题目保证任意城市之间只有唯一的一条路径。换句话说,所有城市形成了一棵 树 。

一棵 子树 是城市的一个子集,且子集中任意城市之间可以通过子集中的其他城市和边到达。两个子树被认为不一样的条件是至少有一个城市在其中一棵子树中存在,但在另一棵子树中不存在。

对于 d 从 1 到 n-1 ,请你找到城市间 最大距离 恰好为 d 的所有子树数目。

请你返回一个大小为 n-1 的数组,其中第 d 个元素(下标从 1 开始)是城市间 最大距离 恰好等于 d 的子树数目。

请注意,两个城市间距离定义为它们之间需要经过的边的数目。

分析:题目描述优点绕,简单来说就是求从1到n-1每个数对应的子集树的个数(不能有重复)。距离为1的简单就是边的个数,后面求距离有点难度,主要是子节点怎么找,还要求子节点内部的最大距离,这里用两次dfs,树形dp(根节点到节点的距离)求解最大距离

class Solution {
    vector<vector<int>> E;
    int N;
public:
    vector<int> countSubgraphsForEachDiameter(int n, vector<vector<int>>& edges) {
        N = n;
        E = vector<vector<int>>(N);
        for(auto &e:edges){
            auto s = e[0]-1;
            auto t = e[1]-1;
            E[s].push_back(t);
            E[t].push_back(s);
        }
        vector<int> ans(N-1);
        for(int st=1;st<(1<<N);st++){
            vector<int> pick;
            for(int i=0;i<N;++i)
                if(st&(1<<i))
                    pick.push_back(i);
            int d = MaxDistance(pick);
            if(d)
                ans[d-1]++;
        }
        return ans;
    }
    
    void dfs(int s, int d, vector<int> &buf){
        // int max_d=0;
        for(auto t:E[s]){
            if(buf[t]==-1){
                buf[t]=d;
                dfs(t, d+1, buf);
                // max_d = max(max_d, 1+dfs(t, d+1, buf));
            }
        }
        // return max_d;
    }
    
    int MaxDistance(vector<int> &pick){
        if(pick.size()==1)
            return 0;
        // printf("Pick:");
        // for(auto p:pick)
        //     printf(" %d", p);
        // printf("\n");
        int root = pick[0];
        vector<int> buf(N, 0);
        for(auto p:pick)
            buf[p]=-1;
        buf[root]=-2;
        dfs(root, 1, buf);
        for(auto p:pick){
            if(buf[p]==-1){
                // printf("Not connect!\n");
                return 0;
            }
            if(buf[p]>buf[root])
                root=p;
        }
        for(auto p:pick)
            buf[p]=-1;
        buf[root]=-2;
        dfs(root, 1, buf);
        int ans=0;
        for(auto p:pick)
            ans = max(ans, buf[p]);
        return ans;
    }
};

作者:JiaLiLue
链接:https://leetcode-cn.com/problems/count-subtrees-with-max-distance-between-cities/solution/qiu-shu-de-zhi-jing-by-jialilue/
来源:力扣(LeetCode)
posted @ 2020-10-11 17:02  青衣素  阅读(271)  评论(0)    收藏  举报