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)
相关推荐
仙俊红26 分钟前
LeetCode322零钱兑换
算法
颖风船29 分钟前
锂电池SOC估计的一种算法(改进无迹卡尔曼滤波)
python·算法·信号处理
551只玄猫43 分钟前
KNN算法基础 机器学习基础1 python人工智能
人工智能·python·算法·机器学习·机器学习算法·knn·knn算法
charliejohn44 分钟前
计算机考研 408 数据结构 哈夫曼
数据结构·考研·算法
POLITE31 小时前
Leetcode 41.缺失的第一个正数 JavaScript (Day 7)
javascript·算法·leetcode
CodeAmaz1 小时前
一致性哈希与Redis哈希槽详解
redis·算法·哈希算法
POLITE32 小时前
Leetcode 42.接雨水 JavaScript (Day 3)
javascript·算法·leetcode
Tim_102 小时前
【算法专题训练】36、前缀树路径和
算法