LeetCode 第422场个人周赛

目录

[Q1. 检查平衡字符串](#Q1. 检查平衡字符串)

原题链接

思路分析

AC代码

[Q2. 到达最后一个房间的最少时间 I](#Q2. 到达最后一个房间的最少时间 I)

原题链接

思路分析

AC代码

[Q3. 到达最后一个房间的最少时间 II](#Q3. 到达最后一个房间的最少时间 II)

原题链接

思路分析

AC代码

[Q4. 统计平衡排列的数目](#Q4. 统计平衡排列的数目)

原题链接

思路分析

AC代码


Q1. 检查平衡字符串

原题链接

Q1. 检查平衡字符串

思路分析

签到题,不说了

时间复杂度:O(N)

AC代码

python 复制代码
class Solution:
    def isBalanced(self, num: str) -> bool:
        num = list(map(ord, num))
        for i in range(len(num)):
            num[i] -= ord('0')
        return sum(num[0::2]) == sum(num[1::2])

Q2. 到达最后一个房间的最少时间 I

原题链接

Q2. 到达最后一个房间的最少时间 I

思路分析

无脑 dij 即可

时间复杂度:O(NM log NM)

AC代码

cpp 复制代码
using i64 = long long;
constexpr i64 inf64 = 1E18 + 7;
int dir[] = {-1, 0, 1, 0, -1};
class Solution {
public:
    int minTimeToReach(vector<vector<int>>& moveTime) {
        int n = moveTime.size(), m = moveTime[0].size();
        std::priority_queue<std::tuple<i64, int, int, int>, std::vector<std::tuple<i64, int, int, int>>, std::greater<std::tuple<i64, int, int, int>>> pq;
        std::vector<std::vector<i64>> dis(n, std::vector<i64>(m, inf64));
        pq.emplace(0, 0, 0, 1);
        dis[0][0] = 0;
        while (pq.size()) {
            auto [d, i, j, w] = pq.top();
            pq.pop();
            
            if (d > dis[i][j]) {
                continue;
            }
            
            for (int k = 0; k < 4; ++ k) {
                auto [ni, nj] = std::pair(i + dir[k], j + dir[k + 1]);
                if (ni < 0 || ni >= n || nj < 0 || nj >= m) {
                    continue;
                }
                i64 nd = std::max<i64>(d, moveTime[ni][nj]) + w;
                i64 nw = 1;
                if (dis[ni][nj] > nd) {
                    dis[ni][nj] = nd;
                    pq.emplace(nd, ni, nj, nw);
                } 
            }
        }
        return dis[n - 1][m - 1];
    }
};

Q3. 到达最后一个房间的最少时间 II

原题链接

Q3. 到达最后一个房间的最少时间 II

思路分析

无脑dij即可

时间复杂度:O(NM log NM)

AC代码

cpp 复制代码
using i64 = long long;
constexpr i64 inf64 = 1E18 + 7;
int dir[] = {-1, 0, 1, 0, -1};
class Solution {
public:
    int minTimeToReach(vector<vector<int>>& moveTime) {
        int n = moveTime.size(), m = moveTime[0].size();
        std::priority_queue<std::tuple<i64, int, int, int>, std::vector<std::tuple<i64, int, int, int>>, std::greater<std::tuple<i64, int, int, int>>> pq;
        std::vector<std::vector<i64>> dis(n, std::vector<i64>(m, inf64));
        pq.emplace(0, 0, 0, 1);
        dis[0][0] = 0;
        while (pq.size()) {
            auto [d, i, j, w] = pq.top();
            pq.pop();
            
            if (d > dis[i][j]) {
                continue;
            }
            
            for (int k = 0; k < 4; ++ k) {
                auto [ni, nj] = std::pair(i + dir[k], j + dir[k + 1]);
                if (ni < 0 || ni >= n || nj < 0 || nj >= m) {
                    continue;
                }
                i64 nd = std::max<i64>(d, moveTime[ni][nj]) + w;
                i64 nw = (w + 1) % 3;
                if (nw == 0) {
                    nw = 1;
                }
                if (dis[ni][nj] > nd) {
                    dis[ni][nj] = nd;
                    pq.emplace(nd, ni, nj, nw);
                } 
            }
        }
        return dis[n - 1][m - 1];
    }
};

Q4. 统计平衡排列的数目

原题链接

Q4. 统计平衡排列的数目

思路分析

记忆化搜索 + 组合数学

考虑 dfs(i, j, k) 为 奇位置的 序列,考虑到填 数字 i,和为 j,长度为 k时的 方案数

如果我们填了 c 个 i,那么 有 cnt[i] - c 个 i 填到 偶数位置

由于要求排列数,而奇偶位置的排列显然都是多重集排列

多重集排列数 = n! / p1! p2!...pk!

由于本题是取模,所以分母可以在递归的时候乘其逆元

即 dfs(i, j, k) = Σ dfs(i + 1, j + c * i, k + c) * inv(fac(c)) * inv(fac(cnt[i] - c))

时间复杂度:O(U^2 N^3),U = 10

AC代码

python 复制代码
P = 1_000_000_007
N = 80
fac = [1] * (N + 1)
inv = [1] * (N + 1)

for i in range(2, N + 1):
    fac[i] = fac[i - 1] * i % P
inv[N] = pow(fac[N], P - 2, P)
for i in range(N - 1, 1, -1):
    inv[i] = (i + 1) * inv[i + 1]


class Solution:
    def countBalancedPermutations(self, num: str) -> int:
        num = list(map(ord, num))
        s = 0
        for i in range(len(num)):
            num[i] -= ord('0')
            s += num[i]

        cnt = Counter(num)

        if s & 1: return 0

        @cache
        def dfs(i: int, j: int, k: int) -> int:
            if j * 2 > s: return 0
            if i == 10:
                return fac[len(num) // 2] * fac[(len(num) + 1) // 2] % P if j * 2 == s and k == len(num) // 2 else 0

            res = 0

            for c in range(cnt[i] + 1):
                res += dfs(i + 1, j + c * i, k + c) * inv[c] * inv[cnt[i] - c] % P
                res %= P

            return res

        dfs.cache_clear()

        return dfs(0, 0, 0)
相关推荐
ShiinaMashirol3 小时前
代码随想录打卡|Day27(合并区间、单调递增的数字、监控二叉树)
java·算法
wuqingshun3141595 小时前
蓝桥杯 5. 交换瓶子
数据结构·c++·算法·职场和发展·蓝桥杯
Demons_kirit5 小时前
Leetcode 2845 题解
算法·leetcode·职场和发展
adam_life6 小时前
http://noi.openjudge.cn/——2.5基本算法之搜索——200:Solitaire
算法·宽搜·布局唯一码
我想进大厂6 小时前
图论---朴素Prim(稠密图)
数据结构·c++·算法·图论
我想进大厂6 小时前
图论---Bellman-Ford算法
数据结构·c++·算法·图论
AIGC大时代6 小时前
高效使用DeepSeek对“情境+ 对象 +问题“型课题进行开题!
数据库·人工智能·算法·aigc·智能写作·deepseek
CODE_RabbitV7 小时前
【深度强化学习 DRL 快速实践】近端策略优化 (PPO)
算法
宝耶8 小时前
面试常问问题:Java基础篇
java·面试·职场和发展
Wendy_robot8 小时前
【滑动窗口+哈希表/数组记录】Leetcode 438. 找到字符串中所有字母异位词
c++·算法·leetcode