第 449 场周赛

3545. 不同字符数量最多为 K 时的最少删除数

贪心的删除出现次数最少的字符

impl Solution {
    pub fn min_deletion(s: String, k: i32) -> i32 {
        let mut cnt = vec![0; 26];
        for c in s.chars() {
            cnt[(c as u8 - b'a') as usize] += 1;
        }
        cnt.sort();
        let mut res = 0;
        for i in 0..(26 - k) as usize {
            res += cnt[i];
        }
        return res;
    }
}

3546. 等和矩阵分割 I

首先统计出每一行每一列的和,然后对于这两个数组分别判断是否存在前缀和等于总和的一半。

impl Solution {
    pub fn can_partition_grid(grid: Vec<Vec<i32>>) -> bool {
        let n = grid.len();
        let m = grid[0].len();
        let mut r = vec![0; n];
        let mut c = vec![0; m];
        let mut sum = 0;
        for i in 0..n as usize{
            for j in 0..m as usize{
                r[i] += grid[i][j];
                c[j] += grid[i][j];
                sum += grid[i][j];
            }
        }
        let mut pre = 0;
        for i in 0..n as usize {
            pre += r[i];
            if pre * 2 == sum {
                return true;
            }
        }
        pre = 0;
        for i in 0.. m as usize {
            pre += c[i];
            if pre * 2 == sum {
                return true;
            }
        }
        return false;       
    }
}

3547. 图中边值的最大和

想了很久,感觉不可做。赛后发现这个题有问题。真实的复杂度应该是阶乘的。

3548. 等和矩阵分割 II

和第二题的思路类似。

这里记前缀和为\(pre\),要删除的数字是\(x\),和是\(total\)

则有\(total - pre = pre - x\)化简可得\(x = total - 2 \times pre\),这样的话可以把\(x=0\)当作是没有删除的情况。并且用哈希表维护\(x\)的值即可快速的判断。

还有一个要特判的点就是如果是第一行,则不能删除中间的元素,否则会导致不联通的情况发生。

class Solution {
    vector<vector<int>> rotate(vector<vector<int>> &a) {
        int m = a.size(), n = a[0].size();
        vector b(n, vector<int>(m));
        for(int i = 0; i < m; i ++) {
            for(int j = 0; j < n; j ++)
                b[j][m - 1 - i] = a[i][j];
        }
        return b;
    }
public:
    bool canPartitionGrid(vector<vector<int>>& grid) {
        long long total = 0;
        for(auto &row : grid)
            for(int x : row)
                total += x;
        auto calc = [&](vector<vector<int>> a) -> bool {
            int m = a.size(), n = a[0].size();

            auto f = [&]() -> bool {
                unordered_set<long long> st = {0};
                long long s = 0;
                for(int i = 0; i < m - 1; i ++) {
                    auto &row = a[i];
                    for(int j = 0; j < n; j ++) {
                        int x = row[j];
                        s += x;
                        if(i > 0 or j == 0 or j == n - 1){
                            st.insert(x);
                        }
                    }
                    if(n == 1) {
                        if(s * 2 == total or s * 2 - total == a[0][0] or s * 2 - total == row[0]) {
                            return true;
                        }
                        continue;
                    }
                    if(st.contains(s * 2 - total)) return true;
                    if(i == 0) {
                        for(int x : row) {
                            st.insert(x);
                        }
                    }
                }
                return false;
            };
            if(f()) return true;
            ranges::reverse(a);
            return f();
        };
        return calc(grid) || calc(rotate(grid));
        
    }
};
posted @ 2025-05-11 17:11  PHarr  阅读(13)  评论(0)    收藏  举报