跳至主要內容

力扣第 348 场周赛

大约 2 分钟

力扣第 348 场周赛

“光芒熄灭了 但我们还在战斗”。

纪念挚友 ming1ing

比赛时间 2023-06-04。本场周赛国服共 389 人 AK。

T1. 最小化字符串长度(3 分)

解题思路

读题题。问题等价于统计不同字符个数。

时间复杂度:O(n)

参考代码

class Solution {
    public int minimizedStringLength(String s) {
        Set<Character> set = new HashSet<>();
        for (char ch : s.toCharArray()) {
            set.add(ch);
        }
        return set.size();
    }
}

T2. 半有序排列(3 分)

解题思路

分类讨论。找出最小值,最大值坐标后:

  • ans = i + (n-1-i) 下标不交叉;
  • ans = i + (n-1-i) - 1 下标交叉;

时间复杂度:O(n)

参考代码

class Solution {
    public int semiOrderedPermutation(int[] nums) {
        int n = nums.length;
        int minIdx = 0, maxIdx = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i] < nums[minIdx]) minIdx = i;
            if (nums[i] > nums[maxIdx]) maxIdx = i;
        }

        int ans = minIdx + (n - 1 - maxIdx);
        return minIdx < maxIdx ? ans : ans - 1;
    }
}

T3. 查询后矩阵的和(5 分)

解题思路

脑筋急转弯。从后往前考虑,已经被修改过的元素不会被再次修改。

时间复杂度:O(q)

参考代码

class Solution {
    public long matrixSumQueries(int n, int[][] queries) {
        Set<Integer> rows = new HashSet<>();
        Set<Integer> cols = new HashSet<>();
        long ans = 0L;
        int q = queries.length;
        for (int i = q - 1; i >= 0; i--) {
            int type = queries[i][0], index = queries[i][1], val = queries[i][2];
            if (type == 0) {
                if (rows.contains(index)) continue;
                ans += (long) (n - cols.size()) * val;
                rows.add(index);
            } else {
                if (cols.contains(index)) continue;
                ans += (long) (n - rows.size()) * val;
                cols.add(index);
            }
        }
        return ans;
    }
}

T4. 统计整数数目(6 分)

解题思路

数位 DP。上下界稍微处理一下即可:([0, num2] 符合要求的数量 减去 [0, num1-1] 符合要求的数量)。

时间复杂度:O(n * max_sum)。其中 n = num2.length

参考代码

import java.math.BigInteger;

class Solution {
    private static final int MOD = (int) (1e9 + 7);
    private int min_sum, max_sum;

    public int count(String num1, String num2, int min_sum, int max_sum) {
        this.min_sum = min_sum;
        this.max_sum = max_sum;
        long ans1 = count(new BigInteger(num1).subtract(BigInteger.ONE).toString());
        long ans2 = count(num2);
        return (int) (((ans2 - ans1) % MOD + MOD) % MOD);
    }

    private char[] s;
    private long[][] dp;

    private long count(String num) {
        s = num.toCharArray();
        int n = num.length();
        dp = new long[n][max_sum + 1];
        for (int i = 0; i < n; i++) {
            Arrays.fill(dp[i], -1);
        }
        return f(0, 0, true, false);
    }

    private long f(int i, int sum, boolean isLimit, boolean isNum) {
        if (i == s.length) {
            if (!isNum) return 0;
            if (sum > max_sum || sum < min_sum) return 0;
            return 1;
        }
        if (sum > max_sum) return 0;
        if (!isLimit && isNum && dp[i][sum] != -1) {
            return dp[i][sum];
        }
        long ans = 0L;
        if (!isNum) {
            ans += f(i + 1, sum, false, false);
            ans %= MOD;
        }
        int down = isNum ? 0 : 1;
        int up = isLimit ? s[i] - '0' : 9;
        for (int d = down; d <= up; d++) {
            ans += f(i + 1, sum + d, isLimit && d == up, true);
            ans %= MOD;
        }
        return dp[i][sum] = ans;
    }
}

(全文完)