# Leetcode 第195场周赛题解

# Problem A - 判断路径是否相交 (opens new window)

直接模拟机器人的行走过程,用一个集合维护当前已经经过的位置。

参考代码(Python3)
class Solution:
    def isPathCrossing(self, path: str) -> bool:
        s = set()
        s.add((0, 0))
        x = 0
        y = 0
        dx = {"N": 0, "S": 0, "E": 1, "W": -1};
        dy = {"N": 1, "S": -1, "E": 0, "W": 0};
        for c in path:
            x += dx[c]
            y += dy[c]
            if (x, y) in s:
                return True;
            s.add((x, y))
        return False
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# Problem B - 检查数组对是否可以被 k 整除 (opens new window)

按余数进行统计,然后考虑kk的奇偶性分别讨论即可。

参考代码(C++)
class Solution {
public:
    bool canArrange(vector<int>& arr, int k) {
        vector<int> cnt(k);
        for (int i : arr)
            cnt[(i % k + k) % k]++;
        if (k & 1) {
            for (int i = 1; i <= k / 2; ++i)
                if (cnt[i] != cnt[k - i])
                    return false;
            if (cnt[0] & 1)
                return false;
            return true;
        } else {
            for (int i = 1; i < k / 2; ++i)
                if (cnt[i] != cnt[k - i])
                    return false;
            if ((cnt[0] & 1) || (cnt[k / 2] & 1))
                return false;
            return true;
        }
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# Problem C - 满足条件的子序列数目 (opens new window)

排序后使用双指针求解。

假设当前右指针位置为rr,左边能够满足nums[i]+nums[r]targetnums[i]+nums[r]\leq targetii的最大值为ll,则最大值为ara_r的子序列中,满足条件的子序列数目为子序列总数减去a0,,ala_0,\cdots,a_l一个都没有取的子序列总数。

参考代码(C++)
const int MOD = 1e9 + 7;

class Solution {
public:
    int numSubseq(vector<int>& nums, int target) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        vector<int> two(n);
        two[0] = 1;
        for (int i = 1; i < n; ++i)
            two[i] = (two[i - 1] << 1) % MOD;
        int ans = 0, l = 0;
        for (int r = n - 1; r >= 0; --r) {
            if (l > r)
                l = r;
            if (nums[l] + nums[r] > target)
                continue;
            while (l < r && nums[l + 1] + nums[r] <= target)
                l++;
            if (l == r)
                ans = (ans + two[r]) % MOD;
            else
                ans = (ans + two[r] - two[r - l - 1]) % MOD;
        }
        if (ans < 0)
            ans += MOD;
        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

# Problem D - 满足不等式的最大值 (opens new window)

凡是含绝对值x|x|的式子,都可以考虑用x=max{x,x}|x|=\max\{x,-x\}进行转化。

本题中,yi+yj+xixj=max{yi+xi+(yjxj),yixi+(yj+xj)}y_i+y_j+|x_i-x_j|=\max\{y_i+x_i+(y_j-x_j),y_i-x_i+(y_j+x_j)\},因此可以用两个单调队列分别降序记录当前可用的yxy-xy+xy+x的值。在更新之前,首先利用xixjk|x_i-x_j|\leq k这一限制条件从队首删除不符合要求的元素。

本题数组已经按照xx升序排列。如果原始数组无序,则首先还需要自行排序。

参考代码(C++)
class Solution {
public:
    int findMaxValueOfEquation(vector<vector<int>>& points, int k) {
        int n = points.size();
        deque<pair<int, int>> plus, minus;
        plus.push_back({points[0][1] + points[0][0], 0});
        minus.push_back({points[0][1] - points[0][0], 0});
        int ans = INT_MIN;
        for (int i = 1; i < n; ++i) {
            while (!plus.empty() && points[plus.front().second][0] < points[i][0] - k)
                plus.pop_front();
            while (!minus.empty() && points[minus.front().second][0] < points[i][0] - k)
                minus.pop_front();
            int cplus = points[i][1] + points[i][0], cminus = points[i][1] - points[i][0];
            if (!plus.empty())
                ans = max(ans, cminus + plus.front().first);
            if (!minus.empty())
                ans = max(ans, cplus + minus.front().first);
            while (!plus.empty() && plus.back().first <= cplus)
                plus.pop_back();
            plus.push_back({cplus, i});
            while (!minus.empty() && minus.back().first <= cminus)
                minus.pop_back();
            minus.push_back({cminus, i});
        }
        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