天天看点

LeetCode #161 场周赛题解(思维 + 水 + 模拟 + 裴蜀定理)

​​LeetCode #161 场周赛​​

(感觉 LeetCode 上的题不需要考虑复杂度,能想出来做法就能过

5247. 交换字符使得字符串相同

题目:给你两个只包含 ‘x’, ‘y’ 的字符串

分析:首先两个字符串 ‘x’,‘y’ 总数不是偶数,都是不行的。

只关心字符串不相同的位置,(x -> y) 或者 (y -> x)。统计两者个数 。两个 (x -> y) 可以用一次操作消除,(y -> x)同理。

class Solution {
public:
    int minimumSwap(string s1, string s2) {
        map<char, int> mp;
        int s1Size = s1.size();
        int ans1 = 0, ans2 = 0;
        for (int i = 0; i < s1Size; i++) {
            if (s1[i] != s2[i]) {
                if (s1[i] == 'x') ans1++;
                else ans2++;
            }
            mp[s1[i]]++; mp[s2[i]]++;
        }
        if ((mp['x'] & 1) || (mp['y'] & 1)) return -1;
        return ans1 / 2 + ans2 / 2 + (ans1 % 2 + ans2 % 2);
    }
};      

5248. 统计「优美子数组」

题目:给一个数组 和 。问奇数个数为

分析:考虑找到了一个元区间 ,刚好奇数个数为 ,且端点都是奇数。统计两端各有多少 0,(分别用 x, y 表示)。那么对于这个区间能构成的子数组数量为

2 2 2 1 2 1 2 2 2
2      

对于 1 2 1 元区间,,则 。

遍历所有元区间即可加和即可。

class Solution {
public:
    int numberOfSubarrays(vector<int>& nums, int k) {
        int ans = 0, n = nums.size();
        int pos[50010], cnt = 0;
        for (int i = 0; i < n; i++) {   // 记录奇数位置的下标
            if (nums[i] & 1) pos[cnt++] = i;
        }
        if (cnt < k) return 0;
        int i = 0, j = k - 1;
        int L = -1; pos[cnt] = n; // 加上边界
        while (j < cnt) {
            int x = pos[i] - L - 1;
            int y = pos[j + 1] - pos[j] - 1;
            L = pos[i];
            i++; j++;
            ans += (x * y + x + y + 1);
        }
        return ans;
    }
};      

大神做法:

首先 是 中的函数,返回一个区间的左右端点,分别代表 。

预处理奇数数量的前缀和。之后对于每一位直接求满足条件的区间长度即可。

class Solution {
public:
    int numberOfSubarrays(vector<int>& a, int k) {
        int n = a.size();
        vector<int> s(n+1);
        for (int i = 1; i <= n; ++ i)
            s[i] = s[i-1]+a[i-1]%2;
        int ret = 0;
        for (int i = 0; i < n; ++ i)
        {
            auto p = equal_range(s.begin(), s.end(), s[i]+k);
            ret += p.second-p.first;
        }
        return ret;
    }
};      

5249. 移除无效的括号

题目:给字符串 s(由括号,小写字母组成),返回有效字符串(括号相对应)。

分析:用栈匹配括号,删去无效括号即可。

class Solution {
public:
    string minRemoveToMakeValid(string s) {
        stack<int> st; string ans;
        vector<int> pos(s.size(), 1);
        for (int i = 0; i < s.size(); i++) {
            if (s[i] == '(') st.push(i);
            else if (s[i] == ')') {
                if (st.empty()) pos[i]--;
                else st.pop();
            }
        }
        while (!st.empty()) {
            pos[st.top()]--; st.pop();
        }
        for (int i = 0; i < s.size(); i++) if (pos[i]) ans += s[i];
        return ans;
    }
};      

5250. 检查「好数组」

题目:

class Solution {
public:
    bool isGoodArray(vector<int>& a) {
        int n = a.size();
        int ret = a[0];
        for (auto x : a) ret = __gcd(ret, x);
        return ret == 1;
    }
};