# Leetcode 第32场双周赛题解

# Problem A - 第k个缺失的正整数 (opens new window)

暴力枚举。

参考代码(C++)
class Solution {
public:
    int findKthPositive(vector<int>& arr, int k) {
        vector<bool> c(2001);
        for (int i : arr)
            c[i] = true;
        int v = 0, i = 0;
        while (v < k) {
            i++;
            if (!c[i])
                v++;
        }
        return i;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Problem B - K次操作转变字符串 (opens new window)

对于需要操作1次的位置,需要在第1,27……次进行操作。 对于需要操作2次的位置,需要在第2,28……次进行操作。 以此类推,要求所需的总次数,只需要计算每一种情况下所需的次数然后求最大值即可。

需要注意的是,题目没有说s和t长度相等,需要先判断一下。

参考代码(C++)
class Solution {
public:
    bool canConvertString(string s, string t, int k) {
        if (s.size() != t.size())
            return false;
        vector<int> cnt(26);
        for (int i = 0; i < s.size(); ++i) {
            int delta = (t[i] - s[i] + 26) % 26;
            cnt[delta]++;
        }
        int hi = 0;
        for (int i = 1; i < 26; ++i)
            hi = max(hi, (cnt[i] - 1) * 26 + i);
        return hi <= k;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# Problem C - 平衡括号字符串的最少插入次数 (opens new window)

稍作改动的经典题——把)换成了))。首先把所有连续奇数个的)都补齐到偶数个,然后再把所有连续)折半,之后就是经典原题了。

计算当前的嵌套深度,如果深度小于0,则添加(将其补至0。字符串全部扫描完后,如果深度不为0,还需要相应地添加))

参考代码(C++)
class Solution {
public:
    int minInsertions(string s) {
        vector<pair<char, int>> v;
        char l = '$';
        int cnt = 0;
        s += "#";
        for (char c : s) {
            if (c == l)
                cnt++;
            else {
                if (cnt > 0)
                    v.emplace_back(l, cnt);
                cnt = 1;
                l = c;
            }
        }
        int ans = 0, bal = 0;
        for (auto p : v) {
            char c = p.first;
            int t = p.second;
            if (c == ')' && t % 2 == 1) {
                ans++;
                t++;
            }
            if (c == '(')
                bal += t;
            else
                bal -= t / 2;
            if (bal < 0) {
                ans -= bal;
                bal = 0;
            }
        }
        ans += bal * 2;
        return ans;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# Problem D - 找出最长的超赞子字符串 (opens new window)

要求子串能够重排成回文串,所有字符的个数中至多有一个奇数。因为只包含0~9,所以可以用一个10位二进制数表示当前每个字符的奇偶状态。在这种表示方法下,超赞字符串对应的状态只能为:

  • 0000000000
  • 0000000001
  • ……
  • 1000000000

这11种状态中的一种。

用一个数组记录每种状态最早出现的位置,然后在遍历过程中,针对每个位置处的状态,看看前缀中是否存在与其异或后结果为好状态的状态。

参考代码(C++)
class Solution {
public:
    int longestAwesome(string s) {
        vector<int> first(1 << 10, -1);
        vector<int> good = {0};
        for (int i = 0; i < 10; ++i)
            good.emplace_back(1 << i);
        first[0] = 0;
        int n = s.size(), state = 0;
        int ans = 0;
        for (int i = 1; i <= n; ++i) {
            int c = s[i - 1] - '0';
            state ^= (1 << c);
            if (first[state] == -1)
                first[state] = i;
            for (int g : good) {
                int need = g ^ state;
                if (first[need] != -1)
                    ans = max(ans, i - first[need]);
            }
        }
        return ans;
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24