首页 > 其他分享 >华为OD刷题C卷 - 每日刷题 23(提取字符串中的最长表达式,模拟目录管理功能 - 完整实现)

华为OD刷题C卷 - 每日刷题 23(提取字符串中的最长表达式,模拟目录管理功能 - 完整实现)

时间:2024-06-11 12:59:38浏览次数:20  
标签:String 23 sum OD long str public 表达式 刷题

1、提取字符串中的最长表达式

目标是从一个给定的字符串中提取出最长的合法简单数学表达式,并计算该表达式的值。如果存在多个同样长度的合法表达式,则选择第一个出现的表达式进行计算。

简单数学表达式的规则:
只包含0-9的数字和+、-、*三种运算符。
所有数字的计算结果不超过long类型的最大值。
表达式中操作符不能连续出现,例如"±-+1"是非法的。
如果有多个相同长度的合法表达式,选择第一个出现的表达式。
表达式必须是最长的合法表达式。

2、(模拟目录管理功能 - 完整实现):

这段 Java 代码是模拟目录管理功能的完整实现。它定义了 Main 类和两个辅助类 TreeNode 与 Tree。Tree 类包含了目录树的数据结构和基本操作,如创建目录、切换目录和获取当前路径。

main 方法处理标准输入中的命令序列,并根据命令更新目录树的状态,最终输出最后一条命令的执行结果。

// Hard.java

package OD340;

import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description 提取字符串中的最长表达式
 * @level 7
 * @score 100
 * @type 双指针、正则表达式、栈
 */


// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Hard {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        System.out.println(getMaxMath(str));

    }

    //提取字符串中最长合法表达式并计算值(只包含两个操作数的,且第一个数带正负号),如有多个长度一样,则返回第一个
    public static long getMaxMath(String str) {
        char[] chars = str.toCharArray();
        int n = chars.length;
        //创建正则 匹配 (带正负号0个或1个) 数字1个或多个,然后是 + - * 必须1个 ,然后是 (不带正负号的数字)1个或多个
        //Pattern pattern = Pattern.compile("^([+-]?\\d+)([+*-]{1}\\d+)$");
        //如果匹配不只两个操作数
        Pattern pattern = Pattern.compile("^([+-]?\\d+)(([+*-]\\d+)+)([+*-]\\d+)$");

        int max = 0;
        long sum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                String sub = str.substring(i, j + 1);
                Matcher matcher = pattern.matcher(sub);
                //如果匹配成功,且长度大于当前保存的最长,则更新
                if (matcher.find() && sub.length() > max) {
                    max = sub.length();
                    sum = cal(sub);
                }
            }
        }
        return sum;
    }


    //计算合法且无括号表达式的值:如 1 + 2 * 3 返回 7
    public static long cal(String str) {
        char[] chars = str.toCharArray();
        int n = chars.length;
        //存放操作数
        Stack<Long> stack = new Stack<>();
        //初始化符号和数字
        long number = 0;
        char sign = '+';
        //默认符号为"+" 即使第一位是-1 会+0 再 -1
        for (int i = 0; i < n; i++) {
            char c = chars[i];
            //如果遇到数字,拼数字
            if (c >= '0' && c <= '9') {
                number = number * 10 + (c - '0');
            }
            //没有括号和空格等不合法行为
            //遇到符号或已经到最后一位,将数字入栈、并刷新符号和数字
            if (!Character.isDigit(c) || i == n - 1) {
                if (sign == '+') {
                    //该数字前面符号是“+”直接入栈
                    stack.push(number);
                } else if (sign == '-') {
                    //该数字前面的符号是“-”,变负数后入栈
                    stack.push(-1 * number);
                } else if (sign == '*') {
                    //该数字前面是乘,弹出一个相乘后再入栈
                    stack.push(stack.pop() * number);
                }
                //刷新符号
                sign = c;
                //刷新数字
                number = 0;
            }
        }
        //将栈中的操作数求和
        long sum = 0;
        for (long i : stack) {
            sum += i;
        }
        return sum;
    }
}

// Main.java

package OD340;

import java.util.Scanner;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description 提取字符串中的最长表达式
 * @level 7
 * @score 100
 * @type 双指针、正则表达式、栈
 */

/**
 * 题目描述
 * 提取字符串中的最长合法简单数学表达式,字符串长度最长的,并计算表达式的值。如果没有,则返回 0
 * <p>
 * 简单数学表达式只能包含以下内容:
 * <p>
 * 0-9数字,符号+-*
 * 说明:
 * <p>
 * 所有数字,计算结果都不超过long
 * 如果有多个长度一样的,请返回第一个表达式的结果
 * 数学表达式,必须是最长的,合法的
 * 操作符不能连续出现,如 +--+1 是不合法的
 * 输入描述
 * 字符串
 * <p>
 * 输出描述
 * 表达式值
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        System.out.println(getMaxMath(str));

    }

    //提取字符串中最长合法表达式并计算值(只包含两个操作数的,且第一个数带正负号),如有多个长度一样,则返回第一个
    public static long getMaxMath(String str) {
        char[] chars = str.toCharArray();
        int n = chars.length;
        //创建正则 匹配 (带正负号0个或1个) 数字1个或多个,然后是 + - * 必须1个 ,然后是 (不带正负号的数字)1个或多个
        Pattern pattern = Pattern.compile("^([+-]?\\d+)([+*-]{1}\\d+)$");
        //如果匹配不只两个操作数

        int max = 0;
        long sum = 0;
        for (int i = 0; i < n; i++) {
            for (int j = i; j < n; j++) {
                String sub = str.substring(i, j + 1);
                Matcher matcher = pattern.matcher(sub);
                //如果匹配成功,且长度大于当前保存的最长,则更新
                if (matcher.find() && sub.length() > max) {
                    max = sub.length();
                    sum = cal(sub);
                }
            }
        }
        return sum;
    }


    //计算合法且无括号表达式的值:如 1 + 2 * 3 返回 7
    public static long cal(String str) {
        char[] chars = str.toCharArray();
        int n = chars.length;
        //存放操作数
        Stack<Long> stack = new Stack<>();
        //初始化符号和数字
        long number = 0;
        char sign = '+';
        //默认符号为"+" 即使第一位是-1 会+0 再 -1
        for (int i = 0; i < n; i++) {
            char c = chars[i];
            //如果遇到数字,拼数字
            if (c >= '0' && c <= '9') {
                number = number * 10 + (c - '0');
            }
            //没有括号和空格等不合法行为
            //遇到符号或已经到最后一位,将数字入栈、并刷新符号和数字
            if (!Character.isDigit(c) || i == n - 1) {
                if (sign == '+') {
                    //该数字前面符号是“+”直接入栈
                    stack.push(number);
                } else if (sign == '-') {
                    //该数字前面的符号是“-”,变负数后入栈
                    stack.push(-1 * number);
                } else if (sign == '*') {
                    //该数字前面是乘,弹出一个相乘后再入栈
                    stack.push(stack.pop() * number);
                }
                //刷新符号
                sign = c;
                //刷新数字
                number = 0;
            }
        }
        //将栈中的操作数求和
        long sum = 0;
        for (long i : stack) {
            sum += i;
        }
        return sum;
    }
}


// Simple.java

package OD340;

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @description 简单版
 * @level 7
 * @score 100
 * @type 双指针、正则表达式、栈
 */

/**
 * 题目描述
 * 提取字符串中的最长合法简单数学表达式,字符串长度最长的,并计算表达式的值。如果没有,则返回 0
 * <p>
 * 简单数学表达式只能包含以下内容:
 * <p>
 * 0-9数字,符号+-*
 * 说明:
 * <p>
 * 所有数字,计算结果都不超过long
 * 如果有多个长度一样的,请返回第一个表达式的结果
 * 数学表达式,必须是最长的,合法的
 * 操作符不能连续出现,如 +--+1 是不合法的
 * 输入描述
 * 字符串
 * <p>
 * 输出描述
 * 表达式值
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Simple {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String str = sc.nextLine();
        //简单合法表达式为只有两个操作数 如 1+1 -1+1 +1+1都是合法的
        //正则包含三部分:开头^(含有0个或1个符号的数字1个到多个) (操作符+-*) (数字1个到多个)$结尾
        Pattern pattern = Pattern.compile("^([+-]?\\d+)([+*-])(\\d+)$");
        int maxLength = 0;
        long sum = 0;
        //遍历
        for (int i = 0; i < str.length(); i++) {
            for (int j = i; j < str.length(); j++) {
                String sub = str.substring(i, j + 1);
                Matcher matcher = pattern.matcher(sub);
                //如果匹配到且长度大于当前保存的长度,则更新
                if (matcher.find() && sub.length() > maxLength) {
                    maxLength = sub.length();
                    //求解 使用matcher.group(1)和matcher.group(3)分别获取两个数字
                    long num1 = Long.parseLong(matcher.group(1));
                    long num2 = Long.parseLong(matcher.group(3));
                    //操作符
                    String sign = matcher.group(2);
                    switch (sign) {
                        case "+":
                            sum = num1 + num2;
                            break;
                        case "-":
                            sum = num1 - num2;
                            break;
                        case "*":
                            sum = num1 * num2;
                            break;
                    }

                }
            }
        }
        System.out.println(sum);
    }
}

package OD341;

import java.util.HashMap;
import java.util.Scanner;

/**
 * @description 模拟目录管理功能
 * @level 6
 * @score 200
 * @url https://hydro.ac/d/HWOD2023/p/OD341
 */
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        //初始化目录树
        Tree tree = new Tree();

        //记录最后一条命令的输出 除了pwd有输出,其他都输出空
        //输出为空时要输出根目录"/" 才能百分百解法
        String command_output = "/";

        outer:
        while (sc.hasNextLine()) {
            String line = sc.nextLine();

            String[] tmp = line.split(" ");

            //命令 mkdir cd pwd
            String cmd_key = tmp[0];
            //参数
            //String cmd_val =  tmp[1];//pwd没有参数,可能会越界
            //常量在前面,防止空指针异常
            if ("pwd".equals(cmd_key)) {
                //pwd不需要参数,有参数的错误输入什么都不需要干
                if (tmp.length != 1) continue;
                //否则,就将当前命令的输出结果保存
                command_output = tree.pwd();
            } else if ("mkdir".equals(cmd_key) || "cd".equals(cmd_key)) {
                //参数只能有1个
                if (tmp.length != 2) continue;

                //目录名
                String cmd_val = tmp[1];

                //除了 cd .. 不需要检测 其他都需要检测文件名是否合法
                if (!(cmd_key.equals("cd") && cmd_val.equals(".."))) {
                    for (int i = 0; i < cmd_val.length(); i++) {
                        char c = cmd_val.charAt(i);
                        //不合法,直接跳到下一个命令
                        if (c < 'a' || c > 'z') continue outer;
                    }
                }

                //实现操作
                if ("mkdir".equals(cmd_key)) {
                    tree.mkdir(cmd_val);
                    //mkdir操作没有输出,清空当前保存的最后输出
                    command_output = "/";
                } else {
                    //cd
                    tree.cd(cmd_val);
                    //清空
                    command_output = "/";
                }
            }
        }
        //输出最后一条命令的输入,如果是mkdir cd 则没有输出
        System.out.println(command_output);
    }

    //节点 包含父目录 子目录<>
    static class TreeNode {
        //目录名
        String curDicName;
        //父目录
        TreeNode fa;
        //子目录:<子目录名,子目录对象>
        HashMap<String, TreeNode> ch;

        //构造方法 新建一个节点<节点名,父目录>
        public TreeNode(String curDicName, TreeNode fa) {
            this.curDicName = curDicName;
            this.fa = fa;
            this.ch = new HashMap<>();
        }
    }

    //目录树
    static class Tree {
        //根节点
        TreeNode root;
        //当前层
        TreeNode cur;

        //默认无参构造方法
        public Tree() {
            //根节点 视为名称为/
            this.root = new TreeNode("/", null);
            this.cur = root;
        }

        //新建目录
        public void mkdir(String dicName) {
            //如果有同名子目录,则不做任务操作
            //子目录名,子目录对象(名称+"/",该子目录的父目录)
            this.cur.ch.putIfAbsent(dicName, new TreeNode(dicName + "/", this.cur));
        }

        //进入目录
        public void cd(String dicName) {
            //cd .. 防止空指针异常
            if ("..".equals(dicName)) {
                //如果上层不为空,则进入上层
                if (this.cur.fa != null) {
                    this.cur = this.cur.fa;
                }
                //如果为空,不进行任何操作
            } else {
                //cd dicName
                //有同名子目录才进入
                if (this.cur.ch.containsKey(dicName)) {
                    //进入
                    this.cur = this.cur.ch.get(dicName);
                }
                //没有同名子目录则不做任何操作
            }
        }

        //pwd
        public String pwd() {
            StringBuilder sb = new StringBuilder();

            //从当前层遍历到root,每次插入到头部,即倒序
            TreeNode cur = this.cur;
            while (cur != null) {
                // c/ -> b/c/ -> a/b/c/ -> /a/b/c/
                sb.insert(0, cur.curDicName);
                cur = cur.fa;
            }
            return sb.toString();
        }
    }
}

标签:String,23,sum,OD,long,str,public,表达式,刷题
From: https://blog.csdn.net/2401_84585615/article/details/139594269

相关文章

  • Xcode 16 beta (16A5171c) 下载 - Apple 平台 IDE
    Xcode16beta(16A5171c)下载-Apple平台IDEIDEforiOS/iPadOS/macOS/watchOS/tvOS/visonOS请访问原文链接:https://sysin.org/blog/apple-xcode-16/,查看最新版。原创作品,转载请保留出处。作者主页:sysin.orgXcode16betaincludesSDKsforiOS18,iPadOS18,tvOS18......
  • VsCode中snippets --- vue自定义代码片段
    vue自定义代码片段Vue2代码片段1、点击文件→首选项→选择配置用户代码片段2、在弹出这个窗口中选择新建全局代码片段文件3、选择后在此处输入文件名后按‘Enter’键确定4、点击确定后会生成以下文件5、替换成以下vue2代码片段6、使用代码片段Vue3代码片段使用defineC......
  • IC693CPU331S CPU 331 Module
    IC693CPU331S  CPU 331 Module板卡控制通常具有较高的实时性能,可以在短的响应时间内进行控制和监测。这是因为板卡控制直接与硬件设备连接,并通过硬件接口进行数据采集和输出控制。它不依赖于外部的通信和传输过程,因此可以实时地对设备进行控制和反馈。PLC控制的实时性能相......
  • 3G2A5-ID218 Input Module
    变频器电源变频器电源主要用于交流电机的变频调速,其在电气传动系统中占据的地位日趋重要,已获得巨大的节能效果。变频器电源主电路均采用交流-直流-交流方案。工频电源通过整流器变成固定的直流电压,然后由大功率晶体管或IGBT组成的PWM高频变换器, 将直流电压逆变成电压、频......
  • [ToneTuneToolkit][023]UGUI的去色,使UI元素变为灰色
    #regionEnvironmentWindows1022H2Unity2022.3.30f1LTSVSCode1.90.0//ToneTuneToolkit下载地址// https://github.com/MirzkisD1Ex0/ToneTuneToolkit.git#endregion 把UGUI的元素去色!变成灰色!!!超级方便!//该项功能已包含至ToneTuneToolkit插件  01.新建场景,新建......
  • LeetCode 409 Longest Palindrome All In One
    LeetCode409LongestPalindromeAllInOneLeetCode409最长回文算法题解Solutions//MapfunctionlongestPalindrome(s:string):number{constmap=newMap();letlen=0;for(leti=0;i<s.length;i++){if(map.has(s[i])){//配对,消元......
  • Vision-Language Models are Zero-Shot Reward Models for Reinforcement Learning
    发表时间:2024(ICLR2024)文章要点:文章提出用预训练的视觉语言模型作为zero-shot的rewardmodel(VLM-RMs)。好处在于可以通过自然语言来给定一个具体的任务,通过VLM-RMs让强化学习基于reward学习这个任务(usingpretrainedvision-languagemodels(VLMs)aszeroshotrewardmodels......
  • 5.23
    与小组成员改善完成如何完善每日心情的记录并且统计出来,根据不同的统计内容进行分析代码行量:166行学习所花时间:1h  packagecom.example.memosystem.activity;importandroid.os.AsyncTask;importandroid.os.Bundle;importandroid.widget.ArrayAdapter;importandroid.wi......
  • 01-前端开发Vscode插件配置
    01自动保存配置02空格渲染方式配置好以后,可以看到代码的空格有几个,以点的方式呈现,1个点表示1个空格03图标插件VSCodeGreatIcons04缩进推荐使用205vscode标记一整块代码文件>>首选项>>设置添加2行代码"editor.bracketPairColorization.enabled":true,"e......
  • 苹果终于要推出真正的 Siri 了吗?|TodayAI
    苹果的语音助手本来应该是一个超越当前形态的存在。现在,13年后,它可能真的准备好了。2011年,苹果与 iPhone 4S一同推出了 Siri。公司发布了一系列广告,展示了如何使用这个新奇的语音助手。这些广告展示了Siri可以完成提醒、天气预报、闹钟等多种任务。广告的重点是Siri......