LeetCode #161 場周賽題解(思維 + 水 + 模擬 + 裴蜀定理)

LeetCode #161 場周賽

(感覺 LeetCode 上的題不需要考慮複雜度,能想出來做法就能過

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

題目:給你兩個只包含 ‘x’, ‘y’ 的字符串 s1,s2s1, s2 ,每次操作可以交換兩個分別位於兩個字符串中的字符,問最少交換幾次可以使字符串變爲完全相同。

分析:首先兩個字符串 ‘x’,‘y’ 總數不是偶數,都是不行的。
只關心字符串不相同的位置,(x -> y) 或者 (y -> x)。統計兩者個數 ans1,ans2ans1, ans2。兩個 (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. 統計「優美子數組」

題目:給一個數組 numsnumskk。問奇數個數爲 kk 的子數組有多少。

分析:考慮找到了一個元區間 (i,j)(i, j),剛好奇數個數爲 kk,且端點都是奇數。統計兩端各有多少 0,(分別用 x, y 表示)。那麼對於這個區間能構成的子數組數量爲 ans=xy+x+y+1ans = x * y + x + y + 1

2 2 2 1 2 1 2 2 2
2

對於 1 2 1 元區間,x=3,y=3x = 3, y = 3,則 ans=33+3+3+1=16ans = 3 * 3 + 3 + 3 + 1 = 16

遍歷所有元區間即可加和即可。

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;
    }
};

大神做法:
首先 equalrange()equalrange()STLSTL 中的函數,返回一個區間的左右端點,分別代表 lowerbound,upperboundlowerbound, upperbound

預處理奇數數量的前綴和。之後對於每一位直接求滿足條件的區間長度即可。

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. 檢查「好數組」

題目:

分析:裴蜀定理:
要使 a1x1+a2x2++anxn=ka_{1} * x_{1}+a_{2} * x_{2}+\ldots+a_{n} * x_{n}=k 有解,gcd(a1+a2++an)kg c d\left(a_{1}+a_{2}+\ldots+a_{n}\right) | k

求所有數最大公約數是否等於 1 即可。

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;
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章