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)
相关推荐
蒋星熠1 小时前
Flutter跨平台工程实践与原理透视:从渲染引擎到高质产物
开发语言·python·算法·flutter·设计模式·性能优化·硬件工程
小欣加油1 小时前
leetcode 面试题01.02判定是否互为字符重排
数据结构·c++·算法·leetcode·职场和发展
3Cloudream1 小时前
LeetCode 003. 无重复字符的最长子串 - 滑动窗口与哈希表详解
算法·leetcode·字符串·双指针·滑动窗口·哈希表·中等
王璐WL2 小时前
【c++】c++第一课:命名空间
数据结构·c++·算法
空白到白2 小时前
机器学习-聚类
人工智能·算法·机器学习·聚类
索迪迈科技2 小时前
java后端工程师进修ing(研一版 || day40)
java·开发语言·学习·算法
zzzsde3 小时前
【数据结构】队列
数据结构·算法
芒克芒克3 小时前
LeetCode 面试经典 150 题:删除有序数组中的重复项(双指针思想解法详解)
算法
青 .3 小时前
数据结构---二叉搜索树的实现
c语言·网络·数据结构·算法·链表