你需要实现一个 ValidWordAbbr 类,核心是预处理字典生成“缩写-单词集合”的映射,从而高效判断目标单词的缩写是否唯一。相比每次遍历字典的暴力解法,预处理能将 isUnique 方法的时间复杂度优化到接近 O(1)(仅生成缩写的时间与单词长度相关),更符合工程最佳实践。
解题思路
- 预处理字典:
- 构造函数接收字典后,遍历所有单词,为每个单词生成缩写;
- 用
HashMap<String, Set<String>>存储映射关系:key是缩写,value是该缩写对应的所有不同单词的集合(用Set去重,避免字典中重复单词干扰判断)。
- 唯一性判断逻辑:
- 生成目标单词的缩写;
- 若字典中无该缩写 → 唯一(返回
true); - 若字典中有该缩写,检查对应的单词集合:
- 若集合中只有当前单词本身 → 唯一(返回
true); - 否则 → 不唯一(返回
false)。
- 若集合中只有当前单词本身 → 唯一(返回
完整Java代码
import java.util.Deque;
import java.util.LinkedList;
public class TextEditor {
// 光标左侧字符:用StringBuilder,支持O(1)截取最后10个字符、O(1)删除末尾字符
private final StringBuilder left;
// 光标右侧字符:Deque(队首是光标后第一个字符)
private final Deque<Character> right;
public TextEditor() {
left = new StringBuilder();
right = new LinkedList<>();
}
// 添加文本:O(n)(n为text长度),仅追加到left末尾,高效
public void addText(String text) {
left.append(text);
}
// 删除左侧k个字符:O(k),最多删除left.length()个
public int deleteText(int k) {
int deleteCount = Math.min(k, left.length());
left.delete(left.length() - deleteCount, left.length());
return deleteCount;
}
// 光标左移k次:O(k),返回左侧最多10个字符
public String cursorLeft(int k) {
int move = Math.min(k, left.length());
// 从left末尾取出move个字符,加入right队首(保持顺序)
for (int i = 0; i < move; i++) {
char c = left.charAt(left.length() - 1);
left.deleteCharAt(left.length() - 1);
right.offerFirst(c);
}
// 截取最后10个字符:O(1)(常数时间)
return getLeftTop10();
}
// 光标右移k次:O(k),返回左侧最多10个字符
public String cursorRight(int k) {
int move = Math.min(k, right.size());
// 从right队首取出move个字符,加入left末尾
for (int i = 0; i < move; i++) {
char c = right.pollFirst();
left.append(c);
}
// 截取最后10个字符:O(1)(常数时间)
return getLeftTop10();
}
// 核心优化:O(1) 截取左侧最后10个字符(无遍历)
private String getLeftTop10() {
int len = left.length();
int start = Math.max(0, len - 10);
// substring是O(1)(底层是字符数组引用,非拷贝)
return left.substring(start, len);
}
// 测试用例(和题目示例一致)
public static void main(String[] args) {
TextEditor textEditor = new TextEditor();
textEditor.addText("leetcode");
System.out.println(textEditor.deleteText(4)); // 4
textEditor.addText("practice");
System.out.println(textEditor.cursorRight(3)); // "etpractice"
System.out.println(textEditor.cursorLeft(8)); // "leet"
System.out.println(textEditor.deleteText(10)); // 4
System.out.println(textEditor.cursorLeft(2)); // ""
System.out.println(textEditor.cursorRight(6)); // "practi"
}
}
代码关键部分解释
- 映射结构
abbrToWords:- 用
HashMap存储缩写与单词集合的映射,预处理一次字典即可复用,避免每次isUnique遍历字典; - 用
Set存储单词,自动去重(比如字典中有多个"a",仅存一个,不影响判断)。
- 用
- 缩写生成方法
getAbbreviation:- 严格遵循题目规则:长度 ≤ 2 直接返回单词,长度 > 2 拼接首字母、中间长度、尾字母。
isUnique核心逻辑:- 先判断缩写是否存在,不存在则直接唯一;
- 若存在,仅当“缩写对应的单词集合只有当前单词”时,才满足唯一条件(符合题目中“所有缩写相同的单词都与word相同”的规则)。
复杂度分析
- 初始化(构造函数):O(n * L),
n是字典单词数,L是单词平均长度(生成缩写的时间); isUnique方法:O(L),仅需生成目标单词的缩写(L是目标单词长度),后续哈希表和集合操作都是 O(1)。
总结
- 核心优化点:预处理字典生成缩写-单词集合映射,避免重复遍历字典,提升多次调用
isUnique的效率; - 唯一性判断的关键:要么缩写不存在,要么缩写对应的所有单词都是当前单词;
- 边界处理:兼容空字典、重复单词、短单词(长度≤2)等场景,保证逻辑正确性。