普通视图

发现新文章,点击刷新页面。
昨天 — 2026年4月7日首页

【宫水三叶】简单模拟题

作者 AC_OIer
2022年4月14日 11:10

模拟

根据题目给定的移动规则可知,机器人总是在外圈移动(共上下左右四条),而移动方向分为四类:

image.png

当行走步数为 $mod = 2 * (w - 1) + 2 * (h - 1)$ 的整数倍时,会回到起始位置,因此我们可以通过维护一个变量 loc 来记录行走的总步数,并且每次将 locmod 进行取模来得到有效步数。

在回答 getPosgetDir 询问时,根据当前 loc 进行分情况讨论(见注释)。

另外还有一个小细节:根据题意,如果当前处于 $(0, 0)$ 位置,并且没有移动过,方向为 East,若移动过,方向则为 South,这可以通过一个变量 moved 来进行特判处理。

代码:

###Java

class Robot {
    String[] ss = new String[]{"East", "North", "West", "South"};
    int w, h, loc; // loc: 有效(取模后)移动步数
    boolean moved; // 记录是否经过移动,用于特判 (0,0) 的方向
    public Robot(int width, int height) {
        w = width; h = height;
    }
    public void step(int num) {
        moved = true;
        loc += num;
        loc %= 2 * (w - 1) + 2 * (h - 1);
    }
    public int[] getPos() {
        int[] info = move();
        return new int[]{info[0], info[1]};
    }
    public String getDir() {
        int[] info = move();
        int x = info[0], y = info[1], dir = info[2];
        // 特殊处理当前在 (0,0) 的情况,当未移动过方向为 East,移动过方向为 South
        if (x == 0 && y == 0) return moved ? ss[3] : ss[0];
        return ss[dir];
    }
    int[] move() {
        if (loc <= w - 1) {
            // 当移动步数范围在 [0,w-1] 时,所在位置为外圈的下方,方向为 East
            return new int[]{loc, 0, 0};
        } else if (loc <= (w - 1) + (h - 1)) {
            // 当移动步数范围在 [w,(w-1)+(h-1)] 时,所在位置为外圈的右方,方向为 North
            return new int[]{w - 1, loc - (w - 1), 1};
        } else if (loc <= 2 * (w - 1) + (h - 1)) {
            // 当移动步数范围在 [(w-1)+(h-1)+1,2*(w-1)+(h-1)] 时,所在位置为外圈的上方,方向为 West
            return new int[]{(w - 1) - (loc - ((w - 1) + (h - 1))), h - 1, 2};
        } else {
            // 当移动步数范围在 [2*(w-1)+(h-1)+1,2*(w-1)+2*(h-1)] 时,所在位置为外圈的左方,方向为 South
            return new int[]{0, (h - 1) - (loc - (2 * (w - 1) + (h - 1))), 3};
        }
    }
}
  • 时间复杂度:$O(1)$
  • 空间复杂度:$O(1)$

最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我 和 加入我们的「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

昨天以前首页

【宫水三叶】简单模拟题

作者 AC_OIer
2022年10月3日 08:33

模拟

根据题意进行模拟即可。

代码:

###Java

class Solution {
    public boolean checkOnesSegment(String s) {
        int n = s.length(), cnt = 0, idx = 0;
        while (idx < n && cnt <= 1) {
            while (idx < n && s.charAt(idx) == '0') idx++;
            if (idx < n) {
                while (idx < n && s.charAt(idx) == '1') idx++;
                cnt++;
            }
        }
        return cnt <= 1;
    }
}

###TypeScript

function checkOnesSegment(s: string): boolean {
    let n = s.length, cnt = 0, idx = 0
    while (idx < n && cnt <= 1) {
        while (idx < n && s[idx] == '0') idx++
        if (idx < n) {
            while (idx < n && s[idx] == '1') idx++
            cnt++
        }
    }
    return cnt <= 1
};

###Python

class Solution:
    def checkOnesSegment(self, s: str) -> bool:
        n, cnt, idx = len(s), 0, 0
        while idx < n and cnt <= 1:
            while idx < n and s[idx] == '0':
                idx += 1
            if idx < n:
                while idx < n and s[idx] == '1':
                    idx += 1
                cnt += 1
        return cnt <= 1
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$

【宫水三叶】简单模拟题

作者 AC_OIer
2022年11月29日 09:18

模拟

最终结果只有「从 0 开始的交替串」和「从 1 开始的交替串」两种。

对于一个长度为 n 的未知序列 A 而言,假设我们需要花费 cnt 次操作将其变为「从 0 开始的交替串」,那么我们想要将其变为「从 1 开始的交替串」则需要 n - cnt 次操作:原本操作的 cnt 个位置不能动,而原本没操作的位置则都需要翻转,从而确保两种交替串对应位均相反。

代码:

###Java

class Solution {
    public int minOperations(String s) {
        int n = s.length(), cnt = 0;
        for (int i = 0; i < n; i++) cnt += (s.charAt(i) - '0') ^ (i & 1);
        return Math.min(cnt, n - cnt);
    }
}

###TypeScript

function minOperations(s: string): number {
    let n = s.length, cnt = 0
    for (let i = 0; i < n; i++) cnt += (s.charCodeAt(i) - '0'.charCodeAt(0)) ^ (i & 1)
    return Math.min(cnt, n - cnt)
}

###Python3

class Solution:
    def minOperations(self, s: str) -> int:
        n, cnt = len(s), 0
        for i, c in enumerate(s):
            cnt += (ord(c) - ord('0')) ^ (i & 1)
        return min(cnt, n - cnt)
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(1)$

最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

【宫水三叶】树的遍历运用题

作者 AC_OIer
2022年5月30日 09:15

递归

容易想到「递归」进行求解,在 DFS 过程中记录下当前的值为多少,假设遍历到当前节点 $x$ 前,记录的值为 $cur$,那么根据题意,我们需要先将 $cur$ 进行整体左移(腾出最后一位),然后将节点 $x$ 的值放置最低位来得到新的值,并继续进行递归。

递归有使用「函数返回值」和「全局变量」两种实现方式。

代码:

###Java

class Solution {
    public int sumRootToLeaf(TreeNode root) {
        return dfs(root, 0);
    }
    int dfs(TreeNode root, int cur) {
        int ans = 0, ncur = (cur << 1) + root.val;
        if (root.left != null) ans += dfs(root.left, ncur);
        if (root.right != null) ans += dfs(root.right, ncur);
        return root.left == null && root.right == null ? ncur : ans;
    }
}

###Java

class Solution {
    int ans = 0;
    public int sumRootToLeaf(TreeNode root) {
        dfs(root, 0);
        return ans;
    }
    void dfs(TreeNode root, int cur) {
        int ncur = (cur << 1) + root.val;
        if (root.left != null) dfs(root.left, ncur);
        if (root.right != null) dfs(root.right, ncur);
        if (root.left == null && root.right == null) ans += ncur;
    }
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:忽略递归带来的额外空间开销,复杂度为 $O(1)$

迭代

自然也可以使用「迭代」进行求解。

为了不引入除「队列」以外的其他数据结构,当我们可以把某个节点 $x$ 放出队列时,先将其的值修改为当前遍历路径对应的二进制数。

代码:

###Java

class Solution {
    public int sumRootToLeaf(TreeNode root) {
        int ans = 0;
        Deque<TreeNode> d = new ArrayDeque<>();
        d.addLast(root);
        while (!d.isEmpty()) {
            TreeNode poll = d.pollFirst();
            if (poll.left != null) {
                poll.left.val = (poll.val << 1) + poll.left.val;
                d.addLast(poll.left);
            }
            if (poll.right != null) {
                poll.right.val = (poll.val << 1) + poll.right.val;
                d.addLast(poll.right);
            }
            if (poll.left == null && poll.right == null) ans += poll.val;
        }
        return ans;
    }
}
  • 时间复杂度:$O(n)$
  • 空间复杂度:$O(n)$

最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我 和 加入我们的「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

【宫水三叶】简单模拟题

作者 AC_OIer
2022年4月24日 08:45

模拟

根据题意进行模拟即可,遍历 $n$ 的二进制中的每一位 $i$,同时记录上一位 $1$ 的位置 $j$,即可得到所有相邻 $1$ 的间距,所有间距取 $\max$ 即是答案。

代码:

###Java

class Solution {
    public int binaryGap(int n) {
        int ans = 0;
        for (int i = 31, j = -1; i >= 0; i--) {
            if (((n >> i) & 1) == 1) {
                if (j != -1) ans = Math.max(ans, j - i);
                j = i;
            }
        }
        return ans;
    }
}
  • 时间复杂度:$O(\log{n})$
  • 空间复杂度:$O(1)$

加餐 & 加练

今日份加餐:【面试高频题】难度 1.5/5,脑筋急转弯类模拟题 🎉🎉🎉

或是考虑加练如下「模拟」题 🍭🍭🍭

题目 题解 难度 推荐指数
6. Z 字形变换 LeetCode 题解链接 中等 🤩🤩🤩
8. 字符串转换整数 (atoi) LeetCode 题解链接 中等 🤩🤩🤩
12. 整数转罗马数字 LeetCode 题解链接 中等 🤩🤩
59. 螺旋矩阵 II LeetCode 题解链接 中等 🤩🤩🤩🤩
65. 有效数字 LeetCode 题解链接 困难 🤩🤩🤩
73. 矩阵置零 LeetCode 题解链接 中等 🤩🤩🤩🤩
89. 格雷编码 LeetCode 题解链接 中等 🤩🤩🤩🤩
166. 分数到小数 LeetCode 题解链接 中等 🤩🤩🤩🤩
260. 只出现一次的数字 III LeetCode 题解链接 中等 🤩🤩🤩🤩
414. 第三大的数 LeetCode 题解链接 中等 🤩🤩🤩🤩
419. 甲板上的战舰 LeetCode 题解链接 中等 🤩🤩🤩🤩
443. 压缩字符串 LeetCode 题解链接 中等 🤩🤩🤩🤩
457. 环形数组是否存在循环 LeetCode 题解链接 中等 🤩🤩🤩🤩
528. 按权重随机选择 LeetCode 题解链接 中等 🤩🤩🤩🤩
539. 最小时间差 LeetCode 题解链接 中等 🤩🤩🤩🤩
726. 原子的数量 LeetCode 题解链接 困难 🤩🤩🤩🤩

注:以上目录整理来自 wiki,任何形式的转载引用请保留出处。


最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我 和 加入我们的「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

【宫水三叶】一题双解 :「lowbit」&「分治」

作者 AC_OIer
2022年4月5日 08:32

模拟 + lowbit

利用一个 int 的二进制表示不超过 $32$,我们可以先将 $32$ 以内的质数进行打表。

从前往后处理 $[left, right]$ 中的每个数 $x$,利用 lowbit 操作统计 $x$ 共有多少位 $1$,记为 $cnt$,若 $cnt$ 为质数,则对答案进行加一操作。

代码:

###Java

class Solution {
    static boolean[] hash = new boolean[40];
    static {
        int[] nums = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
        for (int x : nums) hash[x] = true;
    }
    public int countPrimeSetBits(int left, int right) {
        int ans = 0;
        for (int i = left; i <= right; i++) {
            int x = i, cnt = 0;
            while (x != 0 && ++cnt >= 0) x -= (x & -x);
            if (hash[cnt]) ans++;
        }
        return ans;
    }
}
  • 时间复杂度:$O((right - left) * \log{right})$
  • 空间复杂度:$O(C)$

模拟 + 分治

枚举 $[left, right]$ 范围内的数总是不可避免,上述解法的复杂度取决于复杂度为 $O(\log{x})$ 的 lowbit 操作。

而比 lowbit 更加优秀的统计「二进制 $1$ 的数量」的做法最早在 (题解) 191. 位1的个数 讲过,采用「分治」思路对二进制进行成组统计,复杂度为 $O(\log{\log{x}})$。

代码:

###Java

class Solution {
    static boolean[] hash = new boolean[40];
    static {
        int[] nums = new int[]{2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31};
        for (int x : nums) hash[x] = true;
    }
    public int countPrimeSetBits(int left, int right) {
        int ans = 0;
        for (int i = left; i <= right; i++) {
            int x = i;
            x = (x & 0x55555555) + ((x >>> 1)  & 0x55555555);
            x = (x & 0x33333333) + ((x >>> 2)  & 0x33333333);
            x = (x & 0x0f0f0f0f) + ((x >>> 4)  & 0x0f0f0f0f);
            x = (x & 0x00ff00ff) + ((x >>> 8)  & 0x00ff00ff);
            x = (x & 0x0000ffff) + ((x >>> 16) & 0x0000ffff);
            if (hash[x]) ans++;
        }
        return ans;
    }
}
  • 时间复杂度:$O((right - left) * \log{\log{right}})$
  • 空间复杂度:$O(C)$

其他「位运算」相关内容

考虑加练其他「位运算」相关内容 🍭🍭🍭

题目 题解 难度 推荐指数
137. 只出现一次的数字 II LeetCode 题解链接 中等 🤩🤩🤩
190. 颠倒二进制位 LeetCode 题解链接 简单 🤩🤩🤩
191. 位1的个数 LeetCode 题解链接 简单 🤩🤩🤩
231. 2 的幂 LeetCode 题解链接 简单 🤩🤩🤩
338. 比特位计数 LeetCode 题解链接 简单 🤩🤩🤩
342. 4的幂 LeetCode 题解链接 简单 🤩🤩🤩
461. 汉明距离 LeetCode 题解链接 简单 🤩🤩🤩🤩
477. 汉明距离总和 LeetCode 题解链接 简单 🤩🤩🤩🤩
1178. 猜字谜 LeetCode 题解链接 困难 🤩🤩🤩🤩
剑指 Offer 15. 二进制中1的个数 LeetCode 题解链接 简单 🤩🤩🤩

注:以上目录整理来自 wiki,任何形式的转载引用请保留出处。


最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我 和 加入我们的「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

【宫水三叶】经典构造题

作者 AC_OIer
2022年8月8日 09:39

构造

我们可以定义每个字符的得分:字符 1 得分为 $1$ 分,字符 0 得分为 $-1$ 分。

根据题目对「特殊字符串」的定义可知,给定字符串 s 的总得分为 $0$,且任意前缀串不会出现得分为负数的情况。

考虑将 s 进行划分为多个足够小特殊字符串 item(足够小的含义为每个 item 无法再进行划分),每个 item 的总得分为 $0$。根据 s 定义,必然可恰好划分为多个 item

每次操作可以将相邻特殊字符串进行交换,于是问题转换为将 s 进行重排,求其重排后字典序最大的方案。

首先可以证明一个合法 item 必然满足 1...0 的形式,可通过「反证法」进行进行证明:定义了 item 总得分为 $0$,且长度不为 $0$,因此必然有 10若第一位字符为 0,则必然能够从第一位字符作为起点,找到一个得分为负数的子串,这与 s 本身的定义冲突(s 中不存在得分为负数的前缀串);若最后一位为 1,根据 item 总得分为 $0$,可知当前 item 去掉最后一位后得分为负,也与 s 本身定义冲突(s 中不存在得分为负数的前缀串)。

因此可将构造分两步进行:

  1. 对于每个 item 进行重排,使其调整为字典序最大
  2. 对于 item 之间的位置进行重排,使其整体字典序最大

由于题目没有规定重排后的性质,为第一步调整和第二步调整的保持相对独立,我们只能对 item 中的 1...0 中的非边缘部分进行调整(递归处理子串部分)。

假设所有 item 均被处理后,考虑如何进行重排能够使得最终方案字典序最大。

若有两个 item,分别为 ab,我们可以根据拼接结果 abba 的字典序大小来决定将谁放在前面。

这样根据「排序比较逻辑」需要证明在集合上具有「全序关系」:

我们使用符号 $@$ 来代指我们的「排序」逻辑:

  • 如果 $a$ 必须排在 $b$ 的前面,我们记作 $a @ b$;
  • 如果 $a$ 必须排在 $b$ 的后面,我们记作 $b @ a$;
  • 如果 $a$ 既可以排在 $b$ 的前面,也可以排在 $b$ 的后面,我们记作 $a#b$;

2.1 完全性

具有完全性是指从集合 items 中任意取出两个元素 $a$ 和 $b$,必然满足 $a @ b$、$b @ a$ 和 $a#b$ 三者之一。

这点其实不需要额外证明,因为由 $a$ 和 $b$ 拼接的字符串 $ab$ 和 $ba$ 所在「字典序大小关系中」要么完全相等,要么具有明确的字典序大小关系,导致 $a$ 必须排在前面或者后面。

2.2 反对称性

具有反对称性是指由 $a@b$ 和 $b@a$ 能够推导出 $a#b$。

$a@b$ 说明字符串 $ab$ 的字典序大小数值要比字符串 $ba$ 字典序大小数值大。

$b@a$ 说明字符串 $ab$ 的字典序大小数值要比字符串 $ba$ 字典序大小数值小。

这样,基于「字典序本身满足全序关系」和「数学上的 $a \geqslant b$ 和 $a \leqslant b$ 可推导出 $a = b$」。

得证 $a@b$ 和 $b@a$ 能够推导出 $a#b$。

2.3 传递性

具有传递性是指由 $a@b$ 和 $b@c$ 能够推导出 $a@c$。

我们可以利用「两个等长的拼接字符串,字典序大小关系与数值大小关系一致」这一性质来证明,因为字符串 $ac$ 和 $ca$ 必然是等长的。

接下来,让我们从「自定义排序逻辑」出发,换个思路来证明 $a@c$:

image.png

然后我们只需要证明在不同的 $i$ $j$ 关系之间(共三种情况),$a@c$ 恒成立即可:

  1. 当 $i == j$ 的时候:

image.png

  1. 当 $i > j$ 的时候:

image.png

  1. 当 $i < j$ 的时候:

image.png

综上,我们证明了无论在何种情况下,只要有 $a@b$ 和 $b@c$ 的话,那么 $a@c$ 恒成立。

我们之所以能这样证明「传递性」,本质是利用了自定义排序逻辑中「对于确定任意元素 $a$ 和 $b$ 之间的排序关系只依赖于 $a$ 和 $b$ 的第一个不同元素之间的大小关系」这一性质。

最终,我们证明了该「排序比较逻辑」必然能排序出字典序最大的方案。

代码:

###Java

class Solution {
    public String makeLargestSpecial(String s) {
        if (s.length() == 0) return s;
        List<String> list = new ArrayList<>();
        char[] cs = s.toCharArray();
        for (int i = 0, j = 0, k = 0; i < cs.length; i++) {
            k += cs[i] == '1' ? 1 : -1;
            if (k == 0) {
                list.add("1" + makeLargestSpecial(s.substring(j + 1, i)) + "0");
                j = i + 1;
            }
        }
        Collections.sort(list, (a, b)->(b + a).compareTo(a + b));
        StringBuilder sb = new StringBuilder();
        for (String str : list) sb.append(str);
        return sb.toString();
    }
}

###TypeScript

function makeLargestSpecial(s: string): string {
    const list = new Array<string>()
    for (let i = 0, j = 0, k = 0; i < s.length; i++) {
        k += s[i] == '1' ? 1 : -1
        if (k == 0) {
            list.push('1' + makeLargestSpecial(s.substring(j + 1, i)) + '0')
            j = i + 1
        }
    }
    list.sort((a, b)=>(b + a).localeCompare(a + b));
    return [...list].join("")
};
  • 时间复杂度:$O(n^2)$
  • 空间复杂度:$O(n)$

最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我 和 加入我们的「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

【宫水三叶】位运算应用题

作者 AC_OIer
2022年3月28日 07:06

遍历

根据题意,对 $n$ 的每一位进行遍历检查。

代码:

###Java

class Solution {
    public boolean hasAlternatingBits(int n) {
        int cur = -1;
        while (n != 0) {
            int u = n & 1;
            if ((cur ^ u) == 0) return false;
            cur = u; n >>= 1;
        }
        return true;
    }
}
  • 时间复杂度:$O(\log{n})$
  • 空间复杂度:$O(1)$

位运算

另外一种更为巧妙的方式是利用交替位二进制数性质。

当给定值 $n$ 为交替位二进制数时,将 $n$ 右移一位得到的值 $m$ 仍为交替位二进制数,且与原数 $n$ 错开一位,两者异或能够得到形如 $0000...1111$ 的结果 $x$,此时对 $x$ 执行加法(进位操作)能够得到形如 $0000...10000$ 的结果,将该结果与 $x$ 执行按位与后能够得到全 $0$ 结果。

代码:

###Java

class Solution {
    public boolean hasAlternatingBits(int n) {
        int x = n ^ (n >> 1);
        return (x & (x + 1)) == 0;
    }
}
  • 时间复杂度:$O(1)$
  • 空间复杂度:$O(1)$

同类型加餐

今日份加餐:经典「状态压缩 + 位运算」入门题 🎉🎉

或是考虑加练如下「位运算」题目 🍭🍭🍭

题目 题解 难度 推荐指数
137. 只出现一次的数字 II LeetCode 题解链接 中等 🤩🤩🤩
190. 颠倒二进制位 LeetCode 题解链接 简单 🤩🤩🤩
191. 位1的个数 LeetCode 题解链接 简单 🤩🤩🤩
260. 只出现一次的数字 III LeetCode 题解链接 中等 🤩🤩🤩🤩
405. 数字转换为十六进制数 LeetCode 题解链接 简单 🤩🤩🤩🤩
461. 汉明距离 LeetCode 题解链接 简单 🤩🤩🤩🤩
477. 汉明距离总和 LeetCode 题解链接 简单 🤩🤩🤩🤩
526. 优美的排列 LeetCode 题解链接 中等 🤩🤩🤩

注:以上目录整理来自 wiki,任何形式的转载引用请保留出处。


最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我 和 加入我们的「组队打卡」小群 ,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

【宫水三叶】简单线性 DP 运用题

作者 AC_OIer
2022年11月20日 09:38

线性 DP

为了方便,我们令 pouredkquery_rowquery_glass 分别为 $n$ 和 $m$。

定义 $f[i][j]$ 为第 $i$ 行第 $j$ 列杯子所经过的水的流量(而不是最终剩余的水量)。

起始我们有 $f[0][0] = k$,最终答案为 $\min(f[n][m], 1)$。

不失一般性考虑 $f[i][j]$ 能够更新哪些状态:显然当 $f[i][j]$ 不足 $1$ 的时候,不会有水从杯子里溢出,即 $f[i][j]$ 将不能更新其他状态;当 $f[i][j]$ 大于 $1$ 时,将会有 $f[i][j] - 1$ 的水会等量留到下一行的杯子里,所流向的杯子分别是「第 $i + 1$ 行第 $j$ 列的杯子」和「第 $i + 1$ 行第 $j + 1$ 列的杯子」,增加流量均为 $\frac{f[i][j] - 1}{2}$,即有 $f[i + 1][j] += \frac{f[i][j] - 1}{2}$ 和 $f[i + 1][j + 1] += \frac{f[i][j] - 1}{2}$。

代码:

###Java

class Solution {
    public double champagneTower(int k, int n, int m) {
        double[][] f = new double[n + 10][n + 10];
        f[0][0] = k;
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= i; j++) {
                if (f[i][j] <= 1) continue;
                f[i + 1][j] += (f[i][j] - 1) / 2;
                f[i + 1][j + 1] += (f[i][j] - 1) / 2;
            }
        }
        return Math.min(f[n][m], 1);
    }
}

###TypeScript

function champagneTower(k: number, n: number, m: number): number {
    const f = new Array<Array<number>>()
    for (let i = 0; i < n + 10; i++) f.push(new Array<number>(n + 10).fill(0))
    f[0][0] = k
    for (let i = 0; i <= n; i++) {
        for (let j = 0; j <= i; j++) {
            if (f[i][j] <= 1) continue
            f[i + 1][j] += (f[i][j] - 1) / 2
            f[i + 1][j + 1] += (f[i][j] - 1) / 2
        }
    }
    return Math.min(f[n][m], 1)
}

###Python3

class Solution:
    def champagneTower(self, k: int, n: int, m: int) -> float:
        f = [[0] * (n + 10) for _ in range(n + 10)]
        f[0][0] = k
        for i in range(n + 1):
            for j in range(i + 1):
                if f[i][j] <= 1:
                    continue
                f[i + 1][j] += (f[i][j] - 1) / 2
                f[i + 1][j + 1] += (f[i][j] - 1) / 2
        return min(f[n][m], 1)
  • 时间复杂度:$O(n^2)$
  • 空间复杂度:$O(n^2)$

最后

如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

也欢迎你 关注我,提供写「证明」&「思路」的高质量题解。

所有题解已经加入 刷题指南,欢迎 star 哦 ~

❌
❌