Leetcode Weekly 195 解题报告

Leetcode 5448. Path Crossing
Leetcode 5449. Check If Array Pairs Are Divisible by k
Leetcode 5450. Number of Subsequences That Satisfy the Given Sum Condition
Leetcode 5451. Max Value of Equation
\newline
\newline

Leetcode 5448. Path Crossing

直接模拟这个过程即可,把走过的点的坐标放入一个Set内来检查当前点之前有没有走过。

class Solution {
    public boolean isPathCrossing(String path) {
        Set<String> set = new HashSet<>();
        int i = 0;
        int j = 0;
        set.add("0#0");
        for (char c : path.toCharArray()) {
            switch(c) {
                case 'N':
                    i++;
                    break;
                case 'S':
                    i--;
                    break;
                case 'E':
                    j++;
                    break;
                case 'W':
                    j--;
                    break;
            }
            String key = i + "#" + j;
            if (set.contains(key)) {
                return true;
            }
            set.add(key);
        }
        return false;
    }
}

T i m e : O ( N ) Time: O(N) Time:O(N)
S p a c e : O ( N ) Space:O(N) Space:O(N)

\newline
\newline

Leetcode 5449. Check If Array Pairs Are Divisible by k

两个数之和能被k整除相当于两个数除k的余数加起来等于k。记这些数除以k的余数为r,那么只有 r r r k − r ,   r = 1 , 2 , 3 , . . k − 1 k - r,\space r = 1, 2, 3, .. k - 1 kr, r=1,2,3,..k1能配对, r = = 0 r == 0 r==0和自身配对。不能忘记一种特殊情况是 r = = k / 2 r == k / 2 r==k/2。这时候, r r r也是和自己配对。

class Solution {
    public boolean canArrange(int[] arr, int k) {
        int[] cnt = new int[k];
        for (int a : arr) {
            cnt[(a % k + k) % k]++;
        }
        if ((cnt[0] & 1) != 0) {
            return false;
        }
        int i = 1;
        int j = k - 1;
        while (i < j) {
            if (cnt[i++] != cnt[j--]) {
                return false;
            }
        }
        if ((k & 1) == 0) {
            if ((cnt[k >> 1] & 1) != 0) {
                return false;
            }
        }
        return true;
    }
}

T i m e : O ( N ) Time: O(N) Time:O(N)
S p a c e : O ( K ) Space:O(K) Space:O(K)
\newline
\newline

Leetcode 5450. Number of Subsequences That Satisfy the Given Sum Condition

这一题是本周赛里耗时最多的,因为一开始的思考方向不对。子序列这个说法很具有迷惑性,让我首先去往动态规划和滑动窗口方向去思考,但是收效不佳。而且因为是子序列,要保证相对顺序,所以我没有往排序的方向思考。但是后来我恍然想到,这个问题只是求子序列个数,并没有使用任何子序列的顺序性质,这和求子集的个数完全等价。如果题目换成求子集的个数,那么我会立即想到排序。

排序之后,可以使用双指针从头尾遍历数组,

  • 如果当前 n u m s [ i ] + n u m s [ j ] > t a r g e t nums[i] + nums[j] > target nums[i]+nums[j]>target,那么显然 n u m s [ j ] nums[j] nums[j] 太大了, j j j应该往前移动。
  • 如果和小于等于 t a r g e t target target,那么从 i i i j j j 之间的所有子集都是符合要求。为了不重复计算而且保证子集不为空,我们规定 n u m s [ i ] nums[i] nums[i]
    必须取,也就是 2 j − i 2^{j - i}_{} 2ji个子集,然后 i i i 往后移动。
class Solution {
    private static final int MOD = 1000000007;
    
    public int numSubseq(int[] nums, int target) {
        int ans = 0;
        Arrays.sort(nums);
        int[] twoExpo = new int[nums.length];
        twoExpo[0] = 1;
        for (int i = 1; i < nums.length; ++i) {
            twoExpo[i] = (twoExpo[i - 1] << 1) % MOD;
        }
        int i = 0;
        int j = nums.length - 1;
        while (i <= j) {
            if (nums[i] + nums[j] > target) {
                j--;
            } else {
                ans = (ans + twoExpo[j - i]) % MOD;
                i++;
            }
        }
        return ans;
    }
}

T i m e : O ( N L o g N ) Time: O(NLogN) Time:O(NLogN)
S p a c e : O ( N ) Space:O(N) Space:O(N)
\newline
\newline

Leetcode 5451. Max Value of Equation

本周的最后一题要比上一题简单很多,思路很明确。
等式 y i + y j + ∣ x i − x j ∣ y^{}_{i} + y^{}_{j} + |x^{}_{i} - x^{}_{j}| yi+yj+xixj 相当于 x j + y j + y i − x i x^{}_{j} + y^{}_{j} + y^{}_{i} - x^{}_{i} xj+yj+yixi,如果 j > i j > i j>i,即 x j > x i x^{}_{j} > x^{}_{i} xj>xi

如果从前往后遍历,对于当前的点 ( x j ,   y j ) (x^{}_{j},\space y^{}_{j}) (xj, yj),相当于我们要找到最大的 y i − x i y^{}_{i} - x^{}_{i} yixi。这个只需要维护一个单调递减的队列就行。我们需要在这个队列的头和尾操作。

class Solution {
    private class Point {
        int x;
        int y;

        Point(int x, int y) {
            this.x = x;
            this.y = y;
        }
    }

    public int findMaxValueOfEquation(int[][] points, int k) {
        LinkedList<Point> q = new LinkedList<>();
        int ans = Integer.MIN_VALUE;
        for (int i = 0; i < points.length; ++i) {
            Point p = new Point(points[i][0], points[i][1]);
            while (!q.isEmpty() && p.x - q.peekFirst().x > k) {
                q.pollFirst();
            }
            if (!q.isEmpty()) {
                ans = Math.max(ans, p.x + p.y + getVal(q.peekFirst()));
            }
            while (!q.isEmpty() && getVal(q.peekLast()) < getVal(p)) {
                q.pollLast();
            }
            q.addLast(p);
        }
        return ans;
    }

    private int getVal(Point p) {
        return p.y - p.x;
    }
}

T i m e : O ( N ) Time: O(N) Time:O(N)
S p a c e : O ( N ) Space:O(N) Space:O(N)
\newline
\newline

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aliengod

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值