简易二进制编辑器

题目:简易二进制编辑器

请实现一个简易的二进制文本编辑器。编辑器处理的数字必须是"合法的二进制数字",并且支持一系列操作来修改内容和移动光标。

规则定义

  1. 合法二进制数字:

    • 不能有前导零。

    • 前导零定义:

      • 从左到右,第一个非 '0' 数字之前的所有 '0'。
      • 对于一个全由 '0' 组成的数字,最后一个 '0' 之前的所有 '0'。
    • 合法示例: 1101, 0, 1, 100

    • 非法示例: 00, 01

  2. 初始状态:

    • 编辑器内容为一个给定的二进制数字字符串 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 不含前导零。
  • 第二个参数 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());
    }
}
相关推荐
Otaku love travel15 分钟前
老系统改造增加初始化,自动化数据源配置(tomcat+jsp+springmvc)
java·tomcat·初始化·动态数据源
DKPT28 分钟前
Java设计模式之行为型模式(责任链模式)介绍与说明
java·笔记·学习·观察者模式·设计模式
L_autinue_Star43 分钟前
手写vector容器:C++模板实战指南(从0到1掌握泛型编程)
java·c语言·开发语言·c++·学习·stl
我爱C编程1 小时前
基于Qlearning强化学习的1DoF机械臂运动控制系统matlab仿真
算法
晨岳1 小时前
CentOS 安装 JDK+ NGINX+ Tomcat + Redis + MySQL搭建项目环境
java·redis·mysql·nginx·centos·tomcat
chao_7891 小时前
CSS表达式——下篇【selenium】
css·python·selenium·算法
执笔诉情殇〆1 小时前
前后端分离(java) 和 Nginx在服务器上的完整部署方案(redis、minio)
java·服务器·redis·nginx·minio
chao_7891 小时前
Selenium 自动化实战技巧【selenium】
自动化测试·selenium·算法·自动化
YuTaoShao1 小时前
【LeetCode 热题 100】24. 两两交换链表中的节点——(解法一)迭代+哨兵
java·算法·leetcode·链表
怀旧,1 小时前
【数据结构】8. 二叉树
c语言·数据结构·算法