简易二进制编辑器

题目:简易二进制编辑器

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

规则定义

  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());
    }
}
相关推荐
没有bug.的程序员12 小时前
SOA、微服务、分布式系统的区别与联系
java·jvm·微服务·架构·wpf·日志·gc
LYFlied12 小时前
【每日算法】LeetCode 560. 和为 K 的子数组
前端·数据结构·算法·leetcode·职场和发展
素雪风华12 小时前
只使用Docker+Maven实现全自动化流程部署服务;Docker创建ffmpeg环境;
java·运维·后端·docker·容器·自动化·maven
梦里不知身是客1112 小时前
explain分析SQL语句分析sql语句的优劣
java·数据库·sql
你想考研啊12 小时前
k8s使用kubectl报错
java·docker·kubernetes
Epiphany.55612 小时前
dfn序优化树上背包
算法
nvvas12 小时前
JAVA 关于SpringBoot4新版本阅览
java·spring boot
白宇横流学长12 小时前
基于SpringBoot实现的大创管理系统
java·spring boot·后端
MicroTech202512 小时前
微算法科技(NASDAQ MLGO)区块链混合检测模型优化确保全网防御策略一致性
科技·算法·区块链
LYFlied12 小时前
【每日算法】 LeetCode 394. 字符串解码
前端·数据结构·算法·leetcode·面试·职场和发展