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

回溯题目:字母组合迭代器

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:字母组合迭代器

出处:1286. 字母组合迭代器

难度

5 级

题目描述

要求

设计CombinationIterator \texttt{CombinationIterator}CombinationIterator类:

  • CombinationIterator(string characters, int combinationLength) \texttt{CombinationIterator(string characters, int combinationLength)}CombinationIterator(string characters, int combinationLength)使用有序且字符唯一的小写字母组成的字符串characters \texttt{characters}characters和数字combinationLength \texttt{combinationLength}combinationLength初始化对象。
  • next() \texttt{next()}next()返回字典序的下一个长度为combinationLength \texttt{combinationLength}combinationLength的下一个字母组合。
  • hasNext() \texttt{hasNext()}hasNext()当且仅当存在下一个字母组合时返回true \texttt{true}true

示例

示例 1:

输入:
["CombinationIterator", "next", "hasNext", "next", "hasNext", "next", "hasNext"] \texttt{["CombinationIterator", "next", "hasNext", "next", "hasNext", "next", "hasNext"]}["CombinationIterator", "next", "hasNext", "next", "hasNext", "next", "hasNext"]
[["abc", 2], [], [], [], [], [], []] \texttt{[["abc", 2], [], [], [], [], [], []]}[["abc", 2], [], [], [], [], [], []]
输出:
[null, "ab", true, "ac", true, "bc", false] \texttt{[null, "ab", true, "ac", true, "bc", false]}[null, "ab", true, "ac", true, "bc", false]
解释:
CombinationIterator iterator = new CombinationIterator("abc", 2); \texttt{CombinationIterator iterator = new CombinationIterator("abc", 2);}CombinationIterator iterator = new CombinationIterator("abc", 2);
iterator.next(); \texttt{iterator.next();}iterator.next();// 返回"ab" \texttt{"ab"}"ab"
iterator.hasNext(); \texttt{iterator.hasNext();}iterator.hasNext();// 返回true \texttt{true}true
iterator.next(); \texttt{iterator.next();}iterator.next();// 返回"ac" \texttt{"ac"}"ac"
iterator.hasNext(); \texttt{iterator.hasNext();}iterator.hasNext();// 返回true \texttt{true}true
iterator.next(); \texttt{iterator.next();}iterator.next();// 返回"bc" \texttt{"bc"}"bc"
iterator.hasNext(); \texttt{iterator.hasNext();}iterator.hasNext();// 返回false \texttt{false}false

数据范围

  • 1 ≤ combinationLength ≤ characters.length ≤ 15 \texttt{1} \le \texttt{combinationLength} \le \texttt{characters.length} \le \texttt{15}1combinationLengthcharacters.length15
  • characters \texttt{characters}characters中每个字符按升序排序且各不相同
  • 每组测试数据最多对next \texttt{next}nexthasNext \texttt{hasNext}hasNext调用10 4 \texttt{10}^\texttt{4}104
  • 保证每次调用函数next \texttt{next}next时都存在下一个字母组合

解法

思路和算法

这是一道设计题,要求设计字母组合迭代器。

为了实现迭代器,可以首先生成所有可能的组合列表并按升序排序,然后遍历列表,即可得到下一个字母组合与判断是否存在下一个字母组合。

生成所有可能的组合列表的做法为生成从n nn个字母中选k kk个字母的所有组合,其中n nn是字符串characters \textit{characters}characters的长度,k = combinationLength k = \textit{combinationLength}k=combinationLength。生成所有的k kk个字母的组合的做法是,从左到右遍历字符串characters \textit{characters}characters,每个字母都可以加入组合与不加入组合,对于同一个字母,依次考虑将其加入组合与不将其加入组合,当组合中的字母个数等于k kk时即得到一个目标组合。

由于每个组合的长度固定为k kk,因此在回溯过程中如果遇到不可能得到k kk个字母的组合的情况则可提前返回。如果组合中已有的字母加上剩余的全部字母得到的组合长度仍小于k kk,则当前组合的情况下一定不可能得到k kk个字母的组合,此时可提前返回。

由于字符串characters \textit{characters}characters中的字母按升序排序,因此字典序最小的组合是最前面k kk个字母组成的组合,字典序最大的组合是最后面k kk个字母组成的组合。考虑组合的第index \textit{index}index个字母,如果此时遍历到字符串characters \textit{characters}characters的下标i ii处(i < n − 1 i < n - 1i<n1),则当characters [ i ] \textit{characters}[i]characters[i]加入组合时组合的第index \textit{index}index个字母是characters [ i ] \textit{characters}[i]characters[i],当characters [ i ] \textit{characters}[i]characters[i]不加入组合时存在下标j > i j > ij>i使得组合的第index \textit{index}index个字母是characters [ j ] \textit{characters}[j]characters[j],由于字符串characters \textit{characters}characters中的字母按升序排序,因此characters [ j ] > characters [ i ] \textit{characters}[j] > \textit{characters}[i]characters[j]>characters[i],即characters [ i ] \textit{characters}[i]characters[i]加入组合对应的字母组合小于characters [ i ] \textit{characters}[i]characters[i]不加入组合对应的字母组合。因此,对于同一个字母,依次考虑将其加入组合与不将其加入组合,得到的所有k kk个字母的组合列表的顺序为字典序升序。

得到所有的k kk个字母的组合列表之后,维护当前组合的下标currCombinationIndex \textit{currCombinationIndex}currCombinationIndex,初始时currCombinationIndex = 0 \textit{currCombinationIndex} = 0currCombinationIndex=0。得到下一个字母组合与判断是否存在下一个字母组合的做法如下。

  • 得到下一个字母组合:组合列表的下标currCombinationIndex \textit{currCombinationIndex}currCombinationIndex处的组合nextCombination \textit{nextCombination}nextCombination即为下一个字母组合,得到nextCombination \textit{nextCombination}nextCombination之后,将currCombinationIndex \textit{currCombinationIndex}currCombinationIndex1 11,然后返回nextCombination \textit{nextCombination}nextCombination

  • 判断是否存在下一个字母组合:如果currCombinationIndex \textit{currCombinationIndex}currCombinationIndex小于组合列表的长度,则存在下一个字母组合,返回true \text{true}true,否则返回false \text{false}false

代码

classCombinationIterator{List<String>combinations;Stringcharacters;StringBuffertemp;intcharactersLength,combinationLength;intcombinationsCount;intcurrCombinationIndex;publicCombinationIterator(Stringcharacters,intcombinationLength){this.combinations=newArrayList<String>();this.characters=characters;this.temp=newStringBuffer();this.charactersLength=characters.length();this.combinationLength=combinationLength;backtrack(0);this.combinationsCount=combinations.size();this.currCombinationIndex=0;}publicStringnext(){StringnextCombination=combinations.get(currCombinationIndex);currCombinationIndex++;returnnextCombination;}publicbooleanhasNext(){returncurrCombinationIndex<combinationsCount;}privatevoidbacktrack(intindex){if(temp.length()==combinationLength){combinations.add(temp.toString());}else{if(temp.length()+charactersLength-index<combinationLength){return;}temp.append(characters.charAt(index));backtrack(index+1);temp.deleteCharAt(temp.length()-1);backtrack(index+1);}}}

复杂度分析

  • 时间复杂度:构造方法的时间复杂度是O ( k × C n k ) O(k \times C_n^k)O(k×Cnk),方法next \textit{next}nexthasNext \textit{hasNext}hasNext的时间复杂度是O ( 1 ) O(1)O(1),其中n nn是字符串characters \textit{characters}characters的长度,k = combinationLength k = \textit{combinationLength}k=combinationLength
    构造方法生成从n nn个字母中选k kk个字母的所有组合,可能的组合数共有C n k C_n^kCnk个,对于每个组合需要O ( k ) O(k)O(k)的时间添加到列表中,因此时间复杂度是O ( k × C n k ) O(k \times C_n^k)O(k×Cnk)
    方法next \textit{next}nexthasNext \textit{hasNext}hasNext根据组合列表得到答案,时间复杂度是O ( 1 ) O(1)O(1)

  • 空间复杂度:O ( k × C n k ) ) O(k \times C_n^k))O(k×Cnk)),其中n nn是字符串characters \textit{characters}characters的长度,k = combinationLength k = \textit{combinationLength}k=combinationLength。存储当前组合需要O ( k ) O(k)O(k)的空间,递归调用栈需要O ( n ) O(n)O(n)的空间,存储所有的k kk个字母的组合需要O ( k × C n k ) O(k \times C_n^k)O(k×Cnk)的空间,因此空间复杂度是O ( k × C n k ) O(k \times C_n^k)O(k×Cnk)

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

相关文章:

  • 澳大利亚IT留学生回国求职机构:严谨综述盘点保存 - 虚拟星辰
  • 对于戴尔AWCC占用WMI Provider Host过多资源造成的随机性卡顿解决方法
  • Transformer Engine安装避坑指南:CUDA/PyTorch版本锁链与四步验证法
  • UVa 645 File Mapping
  • 抖音批量下载终极指南:3步搞定无水印视频素材库
  • Eigen 稀疏矩阵操作
  • LeetCode Hot100刷题日志D8
  • eBPF 与 OpenTelemetry 融合:构建分布式追踪的 eBPF 探针
  • Spatial-Agent:大模型驱动的地理分析工作流引擎
  • 如何快速掌握Photon-GAMS光影包:面向Minecraft玩家的完整实战指南
  • QModMaster:免费开源ModBus调试工具终极指南,5分钟快速上手工业通信
  • 167、动态分配策略中 Anchor Ratio 的重新聚类:用 K-Means 调整 YOLOv11 默认 Anchor
  • Douyin-Downloader:抖音内容自动化采集的完整技术解决方案
  • 江诗丹顿中国区官方售后服务网点|官方服务电话及地址权威公示(2026年7月最新) - 江诗丹顿中国服务中心
  • 亨得利官方名表服务中心|热线电话及门店地址权威信息公告(2026年7月更新) - 亨得利官方博客
  • 探索华为eulerfs:新一代NVDIMM文件系统的终极指南
  • Claude Fable 5 扩展:免费访问扩展
  • 积家中国官方售后服务网络全指南|官网认证地址及电话全新启用(2026年7月最新) - 积家中国服务中心
  • LangChain4J:Java原生LLM应用开发核心框架解析
  • myql innodb 锁机制
  • 3步解锁:让Direct3D 8经典游戏在现代系统重获新生的智能方案
  • 亨得利官方名表服务中心|最新服务电话及地址权威信息公告(2026年7月更新) - 亨得利钟表维修中心
  • HBM技术如何解决AI计算内存瓶颈:从原理到实践
  • Tailwind IntelliSense在Cursor中卡顿?1个tsconfig.json参数+2个Cursor插件禁用项+1次LSP重启,5分钟解决97%的智能提示延迟问题
  • C++ 类和对象入门:类的定义、封装、对象大小与 this 指针
  • 江诗丹顿官方直营售后维修网点|官方服务电话及地址权威公示(2026年7月最新) - 江诗丹顿中国服务中心
  • 如何彻底告别百度网盘限速?这款开源解析工具让你免费享受高速下载
  • 2026年7月合肥大疆售后本地化服务全景|交通指引气候养护到店全攻略 - 大品牌推荐
  • 深度技术解析:NxNandManager如何实现Nintendo Switch NAND存储的专业管理
  • 由 Palantir CEO 的观点所展开的行业观察