leetcode
leetcode 2851 ~ 2900
古董键盘

古董键盘

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.

代码结果

运行时间: 57 ms, 内存: 16.7 MB


/* 
 * 思路:
 * 1. 我们可以使用递归和组合的方法来解决这个问题。
 * 2. 使用组合计算选择不同字母和不同按键次数的组合数。
 * 3. 将所有组合数相加并取模。
 */

import java.util.stream.IntStream;

public class AntiqueKeyboardStream {
    private static final int MOD = 1000000007;

    public static int countPossibilities(int k, int n) {
        return IntStream.rangeClosed(1, 26).map(i -> countCombinations(i, k, n)).reduce(0, (a, b) -> (a + b) % MOD);
    }

    private static int countCombinations(int letters, int k, int n) {
        if (n == 0) return 1;
        if (letters == 0) return 0;
        return IntStream.rangeClosed(0, Math.min(k, n))
                        .map(m -> countCombinations(letters - 1, k, n - m))
                        .reduce(0, (a, b) -> (a + b) % MOD);
    }

    public static void main(String[] args) {
        System.out.println(countPossibilities(1, 1)); // 26
        System.out.println(countPossibilities(1, 2)); // 650
    }
}

解释

方法:

此题解利用动态规划的方法解决问题。定义 dp(i, j) 为使用前 i 个字母按 j 次所能产生的不同字符串数量。基本思路是,对于每个字母,我们可以选择按 0 次到 k 次(或者直到 j 次,如果 j 较小)。通过组合数 comb(j, l) 来计算在 j 次按键中选 l 个位置按当前字母的方案数,并用剩余的 (i-1) 个字母填充剩下的 (j-l) 次按键。如果用尽所有字母也无法达到 j 次按键,则返回 0。边界情况是,如果 j 为 0(不需要按键),则有一种可能(即空字符串)。

时间复杂度:

O(n * k)

空间复杂度:

O(n)

代码细节讲解

🦆
在动态规划中,如何确保`dp(i, j)`的计算在不同的`i`和`j`之间正确传递?是否需要初始化某些特定的值来确保逻辑的正确性?
在动态规划中,确保`dp(i, j)`的计算正确传递依赖于正确的初始化和递归关系的建立。在此题中,基本的递归关系是通过组合已知的较小问题(即使用较少的字母或较少的按键次数)来解决较大的问题。初始化特定的值确实是必需的,以确保递归有基础值可依。例如,当`j == 0`时初始化`dp(i, 0) = 1`,意味着不按任何键时,只有一种可能:空字符串。另外,当`i == 0`且`j > 0`时,应初始化为0,因为没有字母可用时不能形成任何字符串。这些初始化值确保了在进行更复杂的计算之前,基础情况已正确处理。
🦆
请解释当`j == 0`时,为什么`dp(i, j)`的值应该是1?这是否意味着对于所有的`i`,空字符串总是一个有效的组合?
当`j == 0`时,`dp(i, j)`的值为1,因为不论有多少可用字母(即无论`i`的值如何),如果不需要进行任何按键操作(即`j == 0`),唯一的可能输出就是空字符串。这确实意味着对于所有的`i`值,空字符串总是一个有效的组合。这是动态规划中一个非常重要的基础情况,因为它为进一步的递归计算提供了初始条件。
🦆
在`if i * k < j`的情况下,返回0的逻辑是什么?为什么当剩余的最大按键次数小于所需的按键次数时,就没有有效的字符串组合?
在`if i * k < j`的情况下,返回值为0的逻辑基于可用资源(字母和每个字母的最大可按次数)与需求(总按键次数)的关系。这里`i * k`代表在当前考虑的字母数量下,最大可能的按键次数(即每个字母都按最大次数`k`)。如果这个最大次数还小于所需的按键次数`j`,则明显不可能形成任何有效的字符串组合,因为按键次数的需求超出了可用的按键次数上限。因此,在这种情况下返回0是合理的,表示没有有效的字符串组合可以生成。

相关问题