这道题是 LeetCode 770. 基本计算器 IV,Hard 难度,核心是:表达式解析 + 变量代换 + 多项式合并 + 按规范排序输出。
下面给你可直接提交的 Java 完整题解,带注释。

思路极简版

1. tokenize:把表达式拆成数字、变量、括号、运算符
2. eval map:把已知变量替换成常数
3. 转成多项式:用栈 + 递归/迭代解析表达式,每一步都用「多项式」表示
4. 多项式运算:加、减、乘、合并同类项
5. 排序输出:先按项次数降序,次数相同按变量名字典序

Java 完整 AC 代码

java

import java.util.*;

public class Solution {
static class Term implements Comparable {
int coeff;
List vars;

    public Term(int coeff, List<String> vars) {
        this.coeff = coeff;
        this.vars = new ArrayList<>(vars);
        Collections.sort(this.vars);
    }

    @Override
    public int compareTo(Term o) {
        if (this.vars.size() != o.vars.size()) {
            return Integer.compare(o.vars.size(), this.vars.size());
        }
        for (int i = 0; i < vars.size(); i++) {
            int cmp = vars.get(i).compareTo(o.vars.get(i));
            if (cmp != 0) return cmp;
        }
        return 0;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Term term = (Term) o;
        return Objects.equals(vars, term.vars);
    }

    @Override
    public int hashCode() {
        return Objects.hash(vars);
    }
}

static class Poly {
    Map<Term, Integer> map = new HashMap<>();

    public Poly() {}
    public Poly(long num) {
        if (num != 0) {
            map.put(new Term((int) num, new ArrayList<>()), (int) num);
        }
    }

    public Poly add(Poly other) {
        Poly res = new Poly();
        for (var e : map.entrySet()) res.map.put(e.getKey(), e.getValue());
        for (var e : other.map.entrySet()) {
            Term t = e.getKey();
            int val = e.getValue();
            res.map.put(t, res.map.getOrDefault(t, 0) + val);
            if (res.map.get(t) == 0) res.map.remove(t);
        }
        return res;
    }

    public Poly sub(Poly other) {
        Poly res = new Poly();
        for (var e : map.entrySet()) res.map.put(e.getKey(), e.getValue());
        for (var e : other.map.entrySet()) {
            Term t = e.getKey();
            int val = e.getValue();
            res.map.put(t, res.map.getOrDefault(t, 0) - val);
            if (res.map.get(t) == 0) res.map.remove(t);
        }
        return res;
    }

    public Poly mul(Poly other) {
        Poly res = new Poly();
        for (var e1 : map.entrySet()) {
            Term t1 = e1.getKey();
            int c1 = e1.getValue();
            for (var e2 : other.map.entrySet()) {
                Term t2 = e2.getKey();
                int c2 = e2.getValue();
                List<String> vs = new ArrayList<>();
                vs.addAll(t1.vars);
                vs.addAll(t2.vars);
                Term t = new Term(0, vs);
                int c = c1 * c2;
                res.map.put(t, res.map.getOrDefault(t, 0) + c);
                if (res.map.get(t) == 0) res.map.remove(t);
            }
        }
        return res;
    }
}

private List<String> tokenize(String s) {
    List<String> tokens = new ArrayList<>();
    int n = s.length(), i = 0;
    while (i < n) {
        char c = s.charAt(i);
        if (c == ' ') {
            i++;
        } else if (c == '(' || c == ')' || c == '+' || c == '-' || c == '*') {
            tokens.add(String.valueOf(c));
            i++;
        } else {
            int j = i;
            while (j < n && Character.isLetterOrDigit(s.charAt(j))) j++;
            tokens.add(s.substring(i, j));
            i = j;
        }
    }
    return tokens;
}

private boolean isNumber(String t) {
    return Character.isDigit(t.charAt(0)) || (t.charAt(0) == '-' && t.length() > 1);
}

private Map<String, Integer> evalMap;
private List<String> tokens;
private int idx;

public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
    tokens = tokenize(expression);
    evalMap = new HashMap<>();
    for (int i = 0; i < evalvars.length; i++) {
        evalMap.put(evalvars[i], evalints[i]);
    }
    idx = 0;
    Poly poly = parseExpr();
    List<Term> list = new ArrayList<>(poly.map.keySet());
    Collections.sort(list);
    List<String> ans = new ArrayList<>();
    for (Term t : list) {
        int c = poly.map.get(t);
        if (c == 0) continue;
        StringBuilder sb = new StringBuilder();
        sb.append(c);
        for (String v : t.vars) {
            sb.append('*').append(v);
        }
        ans.add(sb.toString());
    }
    return ans;
}

private Poly parseExpr() {
    Poly res = parseTerm();
    while (idx < tokens.size() && (tokens.get(idx).equals("+") || tokens.get(idx).equals("-"))) {
        String op = tokens.get(idx++);
        Poly p = parseTerm();
        if (op.equals("+")) res = res.add(p);
        else res = res.sub(p);
    }
    return res;
}

private Poly parseTerm() {
    Poly res = parseFactor();
    while (idx < tokens.size() && tokens.get(idx).equals("*")) {
        idx++;
        Poly p = parseFactor();
        res = res.mul(p);
    }
    return res;
}

private Poly parseFactor() {
    String t = tokens.get(idx++);
    if (t.equals("(")) {
        Poly p = parseExpr();
        idx++;
        return p;
    }
    if (isNumber(t)) {
        return new Poly(Integer.parseInt(t));
    }
    if (evalMap.containsKey(t)) {
        return new Poly(evalMap.get(t));
    }
    Poly p = new Poly();
    p.map.put(new Term(1, Arrays.asList(t)), 1);
    return p;
}

}

代码关键点

1. Term

  • 系数 + 排序好的变量列表
  • 重写  equals/hashCode  用于合并同类项
  • compareTo  用于最后输出排序
    2. Poly
  • Map<Term, Integer> :项 → 系数
  • 实现  add / sub / mul 
    3. 递归下降解析
  • parseExpr :处理 + -
  • parseTerm :处理 *
  • parseFactor :处理数字、变量、括号
    4. 代换
  • 遇到已知变量直接换成常数
  • 未知变量保留为多项式项

如果你需要,我可以再给你:

  • 这道题的逐行中文讲解
  • 或者极简版思路+易错点
    你想要哪个?
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐