• [leetcode] 682 Baseball Game 棒球比赛


    题目:682. 棒球比赛

    你现在是棒球比赛记录员。
    给定一个字符串列表,每个字符串可以是以下四种类型之一:

    1. 整数(一轮的得分):直接表示您在本轮中获得的积分数。
    2. "+"(一轮的得分):表示本轮获得的得分是前两轮有效 回合得分的总和。
    3. "D"(一轮的得分):表示本轮获得的得分是前一轮有效 回合得分的两倍。
    4. "C"(一个操作,这不是一个回合的分数):表示您获得的最后一个有效 回合的分数是无效的,应该被移除。

    每一轮的操作都是永久性的,可能会对前一轮和后一轮产生影响。
    你需要返回你在所有回合中得分的总和。

    • 示例 1:

    输入: ["5","2","C","D","+"]
    输出: 30

    解释:
    第1轮:你可以得到5分。总和是:5。
    第2轮:你可以得到2分。总和是:7。
    操作1:第2轮的数据无效。总和是:5。
    第3轮:你可以得到10分(第2轮的数据已被删除)。总数是:15。
    第4轮:你可以得到5 + 10 = 15分。总数是:30。

    • 示例 2:

    输入: ["5","-2","4","C","D","9","+","+"]
    输出: 27

    解释:
    第1轮:你可以得到5分。总和是:5。
    第2轮:你可以得到-2分。总数是:3。
    第3轮:你可以得到4分。总和是:7。
    操作1:第3轮的数据无效。总数是:3。
    第4轮:你可以得到-4分(第三轮的数据已被删除)。总和是:-1。
    第5轮:你可以得到9分。总数是:8。
    第6轮:你可以得到-4 + 9 = 5分。总数是13。
    第7轮:你可以得到9 + 5 = 14分。总数是27。

    • 注意:

    输入列表的大小将介于1和1000之间。
    列表中的每个整数都将介于-30000和30000之间。

    思路

    每一轮的操作(数字“+”相加, “C”消除, “D”翻倍),都将影响与答案相关的有效数字
    其中:
    - 数字 -- 影响本轮;
    - “+”“D” -- 依赖上一轮有效数字,且只影响本轮;
    - “C” -- 将上一轮有效数字清零,影响有效的上一轮 难点

    • 关键在与如何处理好有效数字:
    1. 有效数字的存储
      • 数组
      • 方法栈
    2. 有效数字的交替
      • 数组存储有效数字,通过下标来对有效数字进行标定
      • 栈将有效数字压入、无效数字弹出(题意很符合先入后出的顺序)
      • 方法栈通过进入和回退来变换环境,进而调整有效数字

    算法实现

    利用数组来存储有效数组,下标来标定有效数字位置

    class Solution {
        public int calPoints(String[] ops) {
            // 存储所有有效数字
            int[] arr = new int[ops.length+2];
            
            // 第一位有效数字的下标 
            // 从2开始 可以避免开头第一个字符不是数字
            int i = 2;
            for (String s : ops) {
                // 通过移动下标i来标定最后一位有效数字的位置
                switch (s) {
                    // 前两位有效数字 i-1 i-2
                    case "+": arr[i] = arr[i-1]+arr[i-2]; i++; break;
                    case "D": arr[i] = 2*arr[i-1]; i++; break;
                    // 擦除前一位有效数字 最后一位有效数字位置-1
                    case "C": arr[i-1] = 0; i--; break;
                    // 添加一位有效数字 最后一位有效数字位置+1
                    default:
                        arr[i] = Integer.valueOf(s);
                        i++;
                }
            }
            
            // 将所有有效数字相加求和
            int sum = 0;
            for (int num : arr) {
                sum += num;
            }
            
            return sum;
        }
    }
    
    • 通过数组来存储有效数字,移动下标来操作
      通过数组来存储有效数字

    利用栈来存储有效数组,pop()和peek()方法来操作有效数字

    class Solution {
        public int calPoints(String[] ops) {
            // 存储所有有效数字的栈
            Stack<Integer> stack = new Stack<>();
            
            for (String s : ops) {
                if ("+".equals(s)) {
                    // 通过peek()可以查看一位有效数字
                    int top = stack.pop();
                    int newtop = stack.peek();
                    // 注意先压入之前弹出的数字
                    stack.push(top);
                    stack.push(top+newtop);
                } else if ("D".equals(s)) {
                    stack.push(stack.peek() * 2);
                } else if ("C".equals(s)) {
                    stack.pop();
                } else {
                    stack.push(Integer.parseInt(s));
                }
            }
            
            int sum = 0;
            for (int num : stack) {
                sum += num;
            }
            
            return sum;
        }
    }
    
    • 利用栈来存储有效数字,pop()和peek()函数来操作
      利用栈来存储有效数字

    利用递归的方法栈形式,通过回退来切换有效数字

    class Solution {
        int index = 0, sum = 0;
        public int calPoints(String[] ops) {
            int len = ops.length;
            if (len == 1) {
                String element = ops[0];
                if (element == "C" || element == "D" || element == "+") return 0;
                return Integer.parseInt(element);
            }
            
            helper(0, 0, ops);
            return sum;
        }
    
        /**
         * 递归求解
         * @param:first 第一位有效数字
         * @param:second 第二位有效数字 更靠近当前操作
         * @param:ops 存储操作字符的字符串数组
        **/
        void helper(int first, int second, String[] ops) {
            // 通过while循环 解决“C“操作回退后的环境
            while (index != ops.length) {
                String c = ops[index++];
                if ("C".equals(c)) {
                    sum -= second;
                    // 此步回退到上一个函数 
                    // 然后进入循环 相当于回退到上两轮的环境
                    return;
                } else if ("D".equals(c)) {
                    sum += second*2;
                    helper(second, second*2, ops);
                } else if ("+".equals(c)) {
                    sum += first + second;
                    helper(second, first+second, ops);
                } else {
                    int num = Integer.parseInt(c);
                    sum += num;
                    helper(second, num, ops);
                }
            }
        }
    }
    
    • 通过方法栈实现环境变换
      利用方法栈实现回溯
    • 以while+递归的角度描述
      递归while原理理解
  • 相关阅读:
    [Angular] Architectures for Huge Angular Based Enterprise
    [Bash] Move and Copy Files and Folders with Bash
    [Bash] Create nested folder in Bash
    [Bash] View Files and Folders in Bash
    [Angular] Expose Angular Component Logic Using State Reducers
    [Angular] Modify User Provided UI with Angular Content Directives
    [Angular] Refactor Angular Component State Logic into Directives
    [Angular] Communicate Between Components Using Angular Dependency Injection
    [Angular] Write Compound Components with Angular’s ContentChild
    java web从零单排第二十一期《Hibernate》主键的生成方式,用户增加与显示用户列表
  • 原文地址:https://www.cnblogs.com/slowbirdoflsh/p/11278809.html
Copyright © 2020-2023  润新知