当前位置: 首页 > news >正文

Kimi LeetCode 3333. 找到初始输入字符串 II Java实现

LeetCode 3333. 找到初始输入字符串 II — Java 实现

参考 doocs/leetcode 官方题解 和 walkccc.me 的滑动窗口优化实现 ,提供两种 Java 实现方案:

---

方法一:动态规划 + 前缀和(官方题解,推荐)

```java
import java.util.ArrayList;
import java.util.List;

class Solution {
public int possibleStringCount(String word, int k) {
final int mod = (int) 1e9 + 7;
List<Integer> nums = new ArrayList<>();
long ans = 1;
int cur = 0;
int n = word.length();

// 将连续相同字符分组,统计每组长度
for (int i = 0; i < n; i++) {
cur++;
if (i == n - 1 || word.charAt(i) != word.charAt(i + 1)) {
if (cur > 1) {
if (k > 0) {
nums.add(cur - 1); // 每组可额外删除的字符数
}
ans = ans * cur % mod; // 总方案数(无长度限制)
}
cur = 0;
k--; // 每组至少选一个字符,k 减少
}
}

// 如果 k <= 0,说明每组至少选一个已经满足长度要求
if (k < 1) {
return (int) ans;
}

int m = nums.size();
// f[i][j] 表示前 i 组中,额外选择 j 个字符的方案数
int[][] f = new int[m + 1][k];
f[0][0] = 1;

for (int i = 1; i <= m; i++) {
int x = nums.get(i - 1); // 第 i 组可额外选择的字符数
long[] s = new long[k + 1];
// 前缀和优化
for (int j = 0; j < k; j++) {
s[j + 1] = (s[j] + f[i - 1][j]) % mod;
}
for (int j = 0; j < k; j++) {
int l = Math.max(0, j - x);
// f[i][j] = sum(f[i-1][j-x] ... f[i-1][j])
f[i][j] = (int) ((s[j + 1] - s[l] + mod) % mod);
}
}

// 计算长度小于 k 的方案数(额外选择少于 k 个字符)
long sum = 0;
for (int j = 0; j < k; j++) {
sum = (sum + f[m][j]) % mod;
}

// 答案 = 总方案数 - 长度小于 k 的方案数
return (int) ((ans - sum + mod) % mod);
}
}
```

---

方法二:滑动窗口优化 DP(空间优化至 O(k))

```java
import java.util.ArrayList;
import java.util.List;

class Solution {
private static final int MOD = 1_000_000_007;

public int possibleStringCount(String word, int k) {
List<Integer> groups = getConsecutiveLetters(word);

// 总方案数(无长度限制):每组长度相乘
long totalCombinations = 1;
for (int group : groups) {
totalCombinations = totalCombinations * group % MOD;
}

// 如果组数 >= k,任何字符串长度都至少为 k
if (k <= groups.size()) {
return (int) totalCombinations;
}

// dp[j] 表示使用已处理组,额外选择 j 个字符的方案数
int[] dp = new int[k];
dp[0] = 1; // 基础情况:空字符串

for (int i = 0; i < groups.size(); ++i) {
int[] newDp = new int[k];
int windowSum = 0;
int group = groups.get(i);

// 滑动窗口:j 至少为 i(前 i 组每组至少额外选 0 个)
for (int j = i; j < k; ++j) {
newDp[j] = (newDp[j] + windowSum) % MOD;
windowSum = (windowSum + dp[j]) % MOD;
// 维护窗口大小为 group
if (j >= group) {
windowSum = (windowSum - dp[j - group] + MOD) % MOD;
}
}
dp = newDp;
}

// 计算无效方案数(长度小于 k)
long invalidCombinations = 0;
for (int count : dp) {
invalidCombinations = (invalidCombinations + count) % MOD;
}

return (int) ((totalCombinations - invalidCombinations + MOD) % MOD);
}

// 返回连续相同字符的分组长度
// e.g. "aabbbc" -> [2, 3, 1]
private List<Integer> getConsecutiveLetters(String word) {
List<Integer> groups = new ArrayList<>();
int group = 1;
for (int i = 1; i < word.length(); ++i) {
if (word.charAt(i) == word.charAt(i - 1)) {
++group;
} else {
groups.add(group);
group = 1;
}
}
groups.add(group);
return groups;
}
}
```

---

核心思路

1. 分组统计:将连续相同字符分组,例如 `"aabbccdd"` → `[2,2,2,2]`。每组至少保留 1 个字符,可额外保留 0 到 `group-1` 个。

2. 总方案数:无长度限制时,每组有 `group` 种选择(保留 1 到 group 个),总方案数为各组长度乘积。

3. 长度约束:要求最终字符串长度 ≥ k。
- 先每组至少选 1 个,消耗 `groups.size()` 个字符。
- 剩余需要 `k - groups.size()` 个额外字符。
- 用 DP 计算额外选择少于 `k - groups.size()` 个字符的方案数,从总数中减去。

4. DP 优化:
- 前缀和:`f[i][j] = sum(f[i-1][j-x] ... f[i-1][j])`,用前缀和 O(1) 计算区间和。
- 滑动窗口:维护大小为 `group` 的窗口,空间优化至 O(k)。

复杂度分析

方法 时间复杂度 空间复杂度
前缀和 DP O(n + m×k) O(m×k)
滑动窗口 DP O(n + m×k) O(k)

其中 `m` 为分组数(`m ≤ n`),`k ≤ 2000`。两种方法均可通过,滑动窗口版本空间更优。

http://www.jsqmd.com/news/1055761/

相关文章:

  • DeepSeek-V4生产级调用:DMXAPI工程实践指南
  • 终极指南:如何通过内存注入实现LOL皮肤实时替换
  • 2026 年湛江市厨卫屋顶地下室防水修缮三家横向测评:吉修匠 99.8 分五星榜首 - 吉修匠
  • HAMSA:基于谱自适应的动态视觉状态空间模型原理与实践
  • GPT Pro 100 和 Pro 200 有什么区别?Codex 用户怎么选
  • 基于扩散模型的两阶段轨迹生成框架SynHAT:原理、实现与应用
  • 西安搬家公司推荐:口碑靠谱 TOP5 测评,选对不花冤枉钱 - 资讯速览
  • 论文AI写作术语有哪些?精选10个常用术语,新手必看 - 掌桥科研-AI论文写作
  • 泸州黄金贵金属回收全指南:六家靠谱门店覆盖全城,安心变现不踩坑 - 清奢黄金上门回收
  • 8G显存跑Qwen35B:llama.cpp+GGUF本地无限Token实战指南
  • i.MX31嵌入式Linux显示驱动开发:从帧缓冲到LCD面板移植实战
  • 河源炸串排行榜实测|避坑指南 + TOP1 宝藏店铺推荐,宵夜认准这家四季炸串 - GrowthUME
  • 工业设备PROFINET接口开发实战:从方案选型到认证测试全流程解析
  • 基于i.MX 6Quad的自动跟拍机器人:嵌入式系统设计实战解析
  • MHY_Scanner:米哈游游戏终极扫码登录工具,实现毫秒级直播抢码自动化
  • 基于CMSIS-DSP与MQX RTOS的嵌入式实时信号处理实战
  • 福州美术培训(少儿美育/中考/艺考)机构推荐:师资、成绩、模式、价格五个维度评估 - 资讯速览
  • 汽车电子角度传感器KMA2x:磁阻技术、全集成与SENT接口实战解析
  • 2026年 扫地机/工业扫地机/厂房扫地机/仓储电动扫地机厂商最新推荐榜单:技术创新与清扫效能口碑之选 - 品牌发掘
  • Windows上的终极APK安装指南:告别复杂模拟器,一键安装Android应用
  • 三步搞定RPG Maker加密资源:浏览器端解密工具终极指南
  • 白山黄金回收优选:六家靠谱店铺推荐,覆盖全市区县安心变现 - 新芸鼎珠宝首饰
  • 常熟公司注销工商代办怎么选?清税、年报、账务资料要先理清 - 资讯速览
  • 如何用Go+Qt5打造个人离线音频库:喜马拉雅FM下载器实战指南
  • 用户口碑佳的AI论文工具排名(2026 最新盘点)
  • Mistral Small 4实战指南:MoE轻量模型高效部署与vLLM生产优化
  • 哈尔滨丰田埃尔法汽车隔音、全车隔音降噪 黑龙江埃尔法汽车音响隔音改装专业户-哈尔滨博士达汽车音响 黑龙江汽车隔音行业NO.1 - 木火炎
  • ComfyUI-AnimateDiff-Evolved完整技术栈深度解析:专业级AI动画生成解决方案
  • 安卓UI自动化测试:uiautomator2与weditor 0.6.4高效组合实战
  • 潜水员戴夫风灵月影修改器下载(20项修改器)已汉化