题目:简易二进制编辑器
请实现一个简易的二进制文本编辑器。编辑器处理的数字必须是"合法的二进制数字",并且支持一系列操作来修改内容和移动光标。
规则定义
-
合法二进制数字:
-
不能有前导零。
-
前导零定义:
- 从左到右,第一个非 '0' 数字之前的所有 '0'。
- 对于一个全由 '0' 组成的数字,最后一个 '0' 之前的所有 '0'。
-
合法示例:
1101
,0
,1
,100
-
非法示例:
00
,01
-
-
初始状态:
- 编辑器内容为一个给定的二进制数字字符串
inputStr
(可能为空)。 - 光标默认在字符串的最右侧。
- 编辑器内容为一个给定的二进制数字字符串
功能要求 (操作指令)
-
0
:在光标位置插入一个数字 '0' 。- 光标停留在新插入数字的右侧。
- 注意: 如果本次插入会导致数字变为非法的"前导零"格式,则不做任何处理。
-
1
:在光标位置插入一个数字 '1' 。- 光标停留在新插入数字的右侧。
- 注意: 如果插入后导致出现前导零(例如,在 "0" 前面插入 "1" 变成 "10" 是合法的,但在 "0" 后面插入 "1" 变成 "01" 是非法的),需要将非法的前导零删除。
-
B
(退格 Backspace):删除光标位置左侧相邻的一个数字。- 光标位置相应左移一位。
- 如果删除后导致出现前导零(例如,从 "101" 中删除 '1' 变成 "01"),需要将前导零删除,并且光标需要移动到最左侧。
- 如果光标已在最左侧(行首),则不做任何处理。
-
L
(左移 Left):光标向左移动一个位置。- 如果光标已在最左侧,则不做任何处理。
-
R
(右移 Right):光标向右移动一个位置。- 如果光标已在最右侧,则不做任何处理。
任务
现给出初始二进制数字字符串 inputStr
,以及一系列操作 cmds
,请依次进行编辑操作,最后返回编辑器内最终的二进制数字字符串。
解答要求
- 时间限制: 1000ms
- 内存限制: 256MB
输入
-
第一个参数
inputStr
:- 一个由 '0' 或 '1' 组成的二进制数字字符串,或空串
""
。 0 <= inputStr.length <= 1000
- 用例保证初始
inputStr
不含前导零。
- 一个由 '0' 或 '1' 组成的二进制数字字符串,或空串
-
第二个参数
cmds
:- 一个表示系列操作的字符串。
1 <= cmds.length <= 1000
cmds
中的字符仅为0
,1
,B
,L
,R
之一。
输出
- 一个二进制数字字符串,可能为空字符串
""
。
样例
输入样例 1
arduino
"10"
"0LLB0R1"
输出样例 1
arduino
"1"
样例 1 解释
操作 | 字符串状态 (x 表示光标) | 解释 |
---|---|---|
初始 | 10x | 初始为 "10",光标在最右侧。 |
0 | 100x | 在末尾插入 '0'。 |
L | 10x0 | 光标左移,在两个 '0' 之间。 |
L | 1x00 | 光标再次左移,在 '1' 和 '0' 之间。 |
B | x0 | 退格删除 '1'。剩下 "00",这有前导零,需规范化为 "0",且光标移到最左侧。 |
0 | x0 | 尝试在最左侧插入 '0'。因为当前字符串是 "0",插入会导致 "00",非法,所以不处理。 |
R | 0x | 光标右移。 |
1 | 1x | 在末尾插入 '1',得到 "01"。这有前导零,需规范化为 "1"。光标也相应调整。 |
最终 | 1x | 最终结果为 "1"。 |
java
import java.util.Scanner;
/**
封装简易二进制编辑器状态和逻辑的类
*/
class BinaryEditor {
// 使用 StringBuilder 作为文本缓冲区,因为它对于频繁的插入和删除操作效率很高
private StringBuilder buffer;
// 记录光标位置,范围从 0 到 buffer.length()
private int cursorPos;
/**
* 构造函数,用初始字符串初始化编辑器
*/
public BinaryEditor(String initialStr) {
// 假设初始字符串是合法的
this.buffer = new StringBuilder(initialStr);
// 光标默认在最后一个数字的右侧
this.cursorPos = initialStr.length();
}
/**
* 循环处理所有命令
* @param cmds 包含所有操作的命令字符串
*/
public void processCommands(String cmds) {
for (char cmd : cmds.toCharArray()) {
switch (cmd) {
case '0': insertZero(); break;
case '1': insertOne(); break;
case 'B': backspace(); break;
case 'L': moveLeft(); break;
case 'R': moveRight(); break;
}
}
}
/**
* 获取编辑器最终的文本内容
*/
public String getText() {
return this.buffer.toString();
}
// --- 各个操作的具体实现 ---
private void insertZero() {
// 规则:如果插入 '0' 会导致非法的前导零,则不做任何处理。重点。
// 非法情况1: 字符串非空,且在最左侧插入 '0' (例如 "101" -> "0101")
// 非法情况2: 字符串本身是 "0",再插入一个 '0' 会变成 "00"
boolean isIllegal = (cursorPos == 0 && buffer.length() > 0) || buffer.toString().equals("0");
if (!isIllegal) {
buffer.insert(cursorPos, '0');
cursorPos++; // 光标右移
}
}
private void insertOne() {
// 直接插入 '1'
buffer.insert(cursorPos, '1');
cursorPos++; // 光标右移
// 重点:插入 '1' 后可能会产生需要移除的前导 '0' (例如 "0" -> "01")
normalize();
}
private void backspace() {
// 如果光标已在最左侧,不做任何处理
if (cursorPos == 0) {
return;
}
// 光标左移一位并删除该位置的字符
cursorPos--;
buffer.deleteCharAt(cursorPos);
// 重点:删除后可能产生前导零 (例如 "101" -> "01"),需要规范化
// 如果规范化操作确实删除了字符,则光标移动到最左侧
if (normalize()) {
cursorPos = 0;
}
}
private void moveLeft() {
if (cursorPos > 0) {
cursorPos--;
}
}
private void moveRight() {
if (cursorPos < buffer.length()) {
cursorPos++;
}
}
/**
* 规范化函数:移除所有非法的前导零。
* @return 如果实际执行了删除操作,返回 true;否则返回 false。
*/
private boolean normalize() {
boolean removed = false;
// 只要字符串长度大于1且以 '0' 开头,就移除 '0'
while (buffer.length() > 1 && buffer.charAt(0) == '0') {
buffer.deleteCharAt(0);
// 因为光标左边的字符被删除了,光标的绝对位置需要左移
cursorPos--;
removed = true;
}
// 防止光标位置变为负数(理论上不会,因为 normalize 前会插入 '1' 或删除后仍有字符)
cursorPos = Math.max(0, cursorPos);
return removed;
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取初始字符串
String inputStr = scanner.nextLine();
// 读取命令字符串
String cmds = scanner.nextLine();
scanner.close();
// 创建编辑器实例
BinaryEditor editor = new BinaryEditor(inputStr);
// 处理所有命令
editor.processCommands(cmds);
// 输出最终结果
System.out.println(editor.getText());
}
}