class039 嵌套类问题的递归解题套路【算法】

简介: class039 嵌套类问题的递归解题套路【算法】

class039 嵌套类问题的递归解题套路

算法讲解039【必备】嵌套类问题的递归解题套路

Code1 772. 基本计算器 III

实现一个基本的计算器来计算简单的表达式字符串。

表达式字符串只包含非负整数,算符+、-、*、, ,左括号(和右括号)。整数除法需要向下截断

你可以假定给定的表达式总是有效的。所有的中间结果的范围均满足[-231,231-1]。

注意:你不能使用任何将字符串作为表达式求值的内置函数,比如eval( ) .

示例1:

输入:s = “1+1”

输出:2

示例2:

输入:s = “6-4/2”

输出:4

示例3:

输入:s =“2*(5+5*2)/3+(6/2+8)"

输出:21

提示:

  • 1 <= s <= 104
  • s 由整数、‘+’、‘-’、‘*’、’ / ‘、’(和’)′组成
  • s是一个有效的表达式

// 含有嵌套的表达式求值

// 测试链接 : https://leetcode.cn/problems/basic-calculator-iii/

思路:f(i)代表:i这段的计算结果

嵌套条件:有括号

退出条件:遇到右括号

package class039;
import java.util.ArrayList;
// 含有嵌套的表达式求值
// 测试链接 : https://leetcode.cn/problems/basic-calculator-iii/
public class Code01_BasicCalculatorIII {
  public static int calculate(String str) {
    where = 0;
    return f(str.toCharArray(), 0);
  }
  public static int where;
  // s[i....]开始计算,遇到字符串终止 或者 遇到)停止
  // 返回 : 自己负责的这一段,计算的结果
  // 返回之间,更新全局变量where,为了上游函数知道从哪继续!
  public static int f(char[] s, int i) {
    int cur = 0;
    ArrayList<Integer> numbers = new ArrayList<>();
    ArrayList<Character> ops = new ArrayList<>();
    while (i < s.length && s[i] != ')') {
      if (s[i] >= '0' && s[i] <= '9') {
        cur = cur * 10 + s[i++] - '0';
      } else if (s[i] != '(') {
        // 遇到了运算符 + - * /
        push(numbers, ops, cur, s[i++]);
        cur = 0;
      } else {
        // i (.....)
        // 遇到了左括号!
        cur = f(s, i + 1);
        i = where + 1;
      }
    }
    push(numbers, ops, cur, '+');
    where = i;
    return compute(numbers, ops);
  }
  public static void push(ArrayList<Integer> numbers, ArrayList<Character> ops, int cur, char op) {
    int n = numbers.size();
    if (n == 0 || ops.get(n - 1) == '+' || ops.get(n - 1) == '-') {
      numbers.add(cur);
      ops.add(op);
    } else {
      int topNumber = numbers.get(n - 1);
      char topOp = ops.get(n - 1);
      if (topOp == '*') {
        numbers.set(n - 1, topNumber * cur);
      } else {
        numbers.set(n - 1, topNumber / cur);
      }
      ops.set(n - 1, op);
    }
  }
  public static int compute(ArrayList<Integer> numbers, ArrayList<Character> ops) {
    int n = numbers.size();
    int ans = numbers.get(0);
    for (int i = 1; i < n; i++) {
      ans += ops.get(i - 1) == '+' ? numbers.get(i) : -numbers.get(i);
    }
    return ans;
  }
}

code2 394. 字符串解码

// 含有嵌套的字符串解码

// 测试链接 : https://leetcode.cn/problems/decode-string/

嵌套条件:有数字

退出条件:遇到右括号

package class039;
// 含有嵌套的字符串解码
// 测试链接 : https://leetcode.cn/problems/decode-string/
public class Code02_DecodeString {
  public static String decodeString(String str) {
    where = 0;
    return f(str.toCharArray(), 0);
  }
  public static int where;
  // s[i....]开始计算,遇到字符串终止 或者 遇到 ] 停止
  // 返回 : 自己负责的这一段字符串的结果
  // 返回之间,更新全局变量where,为了上游函数知道从哪继续!
  public static String f(char[] s, int i) {
    StringBuilder path = new StringBuilder();
    int cnt = 0;
    while (i < s.length && s[i] != ']') {
      if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
        path.append(s[i++]);
      } else if (s[i] >= '0' && s[i] <= '9') {
        cnt = cnt * 10 + s[i++] - '0';
      } else {
        // 遇到 [ 
        // cnt = 7 * ? 
        path.append(get(cnt, f(s, i + 1)));
        i = where + 1;
        cnt = 0;
      }
    }
    where = i;
    return path.toString();
  }
  public static String get(int cnt, String str) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < cnt; i++) {
      builder.append(str);
    }
    return builder.toString();
  }
}

code3 726. 原子的数量

// 含有嵌套的分子式求原子数量

// 测试链接 : https://leetcode.cn/problems/number-of-atoms/

思路:遇到大写和(意味着要结算历史,历史数据包含name或map以及cnt

package class039;
import java.util.TreeMap;
// 含有嵌套的分子式求原子数量
// 测试链接 : https://leetcode.cn/problems/number-of-atoms/
public class Code03_NumberOfAtoms {
  public static String countOfAtoms(String str) {
    where = 0;
    TreeMap<String, Integer> map = f(str.toCharArray(), 0);
    StringBuilder ans = new StringBuilder();
    for (String key : map.keySet()) {
      ans.append(key);
      int cnt = map.get(key);
      if (cnt > 1) {
        ans.append(cnt);
      }
    }
    return ans.toString();
  }
  public static int where;
  // s[i....]开始计算,遇到字符串终止 或者 遇到 ) 停止
  // 返回 : 自己负责的这一段字符串的结果,有序表!
  // 返回之间,更新全局变量where,为了上游函数知道从哪继续!
  public static TreeMap<String, Integer> f(char[] s, int i) {
    // ans是总表
    TreeMap<String, Integer> ans = new TreeMap<>();
    // 之前收集到的名字,历史一部分
    StringBuilder name = new StringBuilder();
    // 之前收集到的有序表,历史一部分
    TreeMap<String, Integer> pre = null;
    // 历史翻几倍
    int cnt = 0;
    while (i < s.length && s[i] != ')') {
      if (s[i] >= 'A' && s[i] <= 'Z' || s[i] == '(') {
        fill(ans, name, pre, cnt);
        name.setLength(0);
        pre = null;
        cnt = 0;
        if (s[i] >= 'A' && s[i] <= 'Z') {
          name.append(s[i++]);
        } else {
          // 遇到 (
          pre = f(s, i + 1);
          i = where + 1;
        }
      } else if (s[i] >= 'a' && s[i] <= 'z') {
        name.append(s[i++]);
      } else {
        cnt = cnt * 10 + s[i++] - '0';
      }
    }
    fill(ans, name, pre, cnt);
    where = i;
    return ans;
  }
  public static void fill(TreeMap<String, Integer> ans, StringBuilder name, TreeMap<String, Integer> pre, int cnt) {
    if (name.length() > 0 || pre != null) {
      cnt = cnt == 0 ? 1 : cnt;
      if (name.length() > 0) {
        String key = name.toString();
        ans.put(key, ans.getOrDefault(key, 0) + cnt);
      } else {
        for (String key : pre.keySet()) {
          ans.put(key, ans.getOrDefault(key, 0) + pre.get(key) * cnt);
        }
      }
    }
  }
}


相关文章
|
1月前
|
算法 Python
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果
在Python编程中,分治法、贪心算法和动态规划是三种重要的算法。分治法通过将大问题分解为小问题,递归解决后合并结果;贪心算法在每一步选择局部最优解,追求全局最优;动态规划通过保存子问题的解,避免重复计算,确保全局最优。这三种算法各具特色,适用于不同类型的问题,合理选择能显著提升编程效率。
49 2
|
2月前
|
存储 算法 Java
Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性
Java Set因其“无重复”特性在集合框架中独树一帜。本文解析了Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定数据结构和算法确保元素唯一性,并提供了最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的hashCode()与equals()方法。
45 4
|
2月前
|
算法 搜索推荐 Shell
数据结构与算法学习十二:希尔排序、快速排序(递归、好理解)、归并排序(递归、难理解)
这篇文章介绍了希尔排序、快速排序和归并排序三种排序算法的基本概念、实现思路、代码实现及其测试结果。
32 1
|
6月前
|
存储 算法 程序员
数据结构与算法===递归
数据结构与算法===递归
|
2月前
|
算法 Java 程序员
【算法每日一练及解题思路】有n级台阶,一次只能上1级或2级,共有多少种走法?
本文深入解析了“爬楼梯问题”,探讨了递归与迭代两种解法,并提供了Java代码实现。通过分析问题本质,帮助读者理解动态规划技巧,提高解决实际编程问题的能力。关键词:Java, 算法, 动态规划, 爬楼梯问题, 递归, 迭代。
111 0
|
2月前
|
算法 定位技术
数据结构与算法学习九:学习递归。递归的经典实例:打印问题、阶乘问题、递归-迷宫问题、八皇后问题
本文详细介绍了递归的概念、重要规则、形式,并展示了递归在解决打印问题、阶乘问题、迷宫问题和八皇后问题等经典实例中的应用。
52 0
|
2月前
|
算法 C++
【算法解题思想】动态规划+深度优先搜索(C/C++)
【算法解题思想】动态规划+深度优先搜索(C/C++)
|
4月前
|
搜索推荐 算法 Java
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
52 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
|
4月前
|
算法
【算法】递归、搜索与回溯——汉诺塔
【算法】递归、搜索与回溯——汉诺塔
|
4月前
|
数据采集 算法 数据可视化
基于K-Means聚类算法对球员数据的聚类分析,可以自主寻找最优聚类数进行聚类
本文介绍了一个基于K-Means聚类算法的NBA球员数据分析项目,该项目通过采集和分析球员的得分、篮板、助攻等统计数据,使用轮廓系数法和拐点法确定最优聚类数,将球员分为不同群组,并提供了一个可视化界面以便直观比较不同群组的球员表现。
基于K-Means聚类算法对球员数据的聚类分析,可以自主寻找最优聚类数进行聚类
下一篇
DataWorks