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)
相关推荐
木子墨51620 分钟前
LeetCode 热题 100 精讲 | 计算几何篇:点积叉积 · 线段相交 · 凸包 · 多边形面积
c++·算法·leetcode·职场和发展·动态规划
源码之家30 分钟前
计算机毕业设计:Python棉花产业数据可视化与预测系统 Django框架 ARIMA算法 数据分析 可视化 爬虫 大数据 大模型(建议收藏)✅
人工智能·python·算法·信息可视化·数据挖掘·django·课程设计
py有趣30 分钟前
力扣热门100题之最小路径和
算法·leetcode
qeen8737 分钟前
【算法笔记】前缀和经典题目解析
c语言·c++·笔记·学习·算法
Je1lyfish40 分钟前
Haskell 初探
开发语言·笔记·算法·rust·lisp·抽象代数
im_AMBER1 小时前
Leetcode 159 无重复字符的最长子串 | 长度最小的子数组
javascript·数据结构·学习·算法·leetcode
浮芷.1 小时前
微观搜打撤:基于鸿蒙flutter的内存快照算法的局内外状态隔离与高阶背包系统设计
算法·flutter·华为·开源·harmonyos·鸿蒙
郝学胜-神的一滴1 小时前
[力扣 105]二叉树前中后序遍历精讲:原理、实现与二叉树还原
数据结构·c++·算法·leetcode·职场和发展
sheeta19981 小时前
LeetCode 每日一题笔记 日期:2026.04.20 题目:2078.两栋颜色不同而距离最远的房子
笔记·算法·leetcode
WL_Aurora1 小时前
二叉树高频考点:后序+中序推导前序与层序遍历
python·算法·深度优先