第271场力扣周赛

本周ac三个题,1164 / 4561。

5952. 环和杆

数组记录每根杆,位运算1,2,4表示三种颜色,按位取或。最后统计三位全为1的杆。时间O(N),空间O(N)。

class Solution {
    public int countPoints(String rings) {
        int[] nums = new int[10];
        int i = 0;
        while (i < rings.length()) {
            char ch = rings.charAt(i);
            nums[rings.charAt(i + 1) - '0'] |= ch == 'R' ? 1 : ch == 'G' ? 2 : 4;
            i += 2;
        }
        int cnt = 0;
        for (i = 0; i < nums.length; i++) {
            if (nums[i] == 7) {
                cnt++;
            }
        }
        return cnt;
    }
}

5953. 子数组范围和

暴力法:枚举左右边界,维护最大值最小值,求和注意溢出用long。时间O(N^2),空间O(1)。单调栈法可以优化时间到O(N)。

class Solution {
    public long subArrayRanges(int[] nums) {
        if (nums.length == 1) {
            return 0;
        }
        long sum = 0;
        for (int i = 0; i < nums.length; i++) {
            int max = nums[i], min = nums[i];
            for (int j = i + 1; j < nums.length; j++) {
                max = Math.max(max, nums[j]);
                min = Math.min(min, nums[j]);
                sum = sum + (max - min);
            }
        }
        return sum;
    }
}

5954. 给植物浇水 II

模拟,把条件都考虑到,没什么问题。时间O(N),空间O(1)。

class Solution {
    public int minimumRefill(int[] plants, int capacityA, int capacityB) {
        int a = 0, b = plants.length - 1, waterA = capacityA, waterB = capacityB;
        int cnt = 0;
        while (a <= b) {
            if (a == b) {
                if (waterB > waterA) {
                    if (waterB < plants[b]) {
                        cnt++;
                    }
                } else {
                    if (waterA < plants[a]) {
                        cnt++;
                    }
                }
            } else {
                if (waterA < plants[a]) {
                    cnt++;
                    waterA = capacityA;
                }
                if (waterB < plants[b]) {
                    cnt++;
                    waterB = capacityB;
                }
                waterA -= plants[a];
                waterB -= plants[b];
            }
            a++;
            b--;
        }
        return cnt;
    }
}

5955. 摘水果

最大值一定只能调头一次,枚举线段[l,r]。分别枚举:先向左走i步,再向右走k-i步;先向右走i步,再向左走k-i步,计算范围内覆盖了多少水果,更新最大值。利用前缀和计算范围内水果数。

class Solution {
    public int maxTotalFruits(int[][] fruits, int startPos, int k) {
        int[] nums = new int[500000];
        int[] preSum = new int[500000];
        for (int[] f : fruits) {
            nums[f[0]] = f[1];
        }
        preSum[0] = nums[0];
        for (int i = 1; i < preSum.length; i++) {
            preSum[i] += preSum[i - 1] + nums[i];
        }
        int MAX = preSum.length - 1, MIN = 0;
        int res = 0;
        // 先向左走i步
        for (int i = 0; i <= k; i++) {
            int left = Math.max(MIN, startPos - i);
            int right = Math.min(MAX, left + k - i);
            int cnt = preSum[right] - (left == 0 ? 0 : preSum[left - 1]);
            res = Math.max(cnt, res);
        }
        // 先向右走i步
        for (int i = 0; i<=k;i++) {
            int right = Math.min(MAX,startPos + i);
            int left = Math.max(MIN, right - k + i);
            int cnt = preSum[right] - (left == 0 ? 0 : preSum[left - 1]);
            res = Math.max(cnt, res);
        }
        return res;
    }
}

下次周赛加油! 

你可能感兴趣的:(leetcode,算法)