美团算法专项面经:二叉树遍历、栈与队列、贪心算法、字符串匹配

20 阅读5分钟

上篇聊完架构设计,这篇回到算法。美团算法面试中等偏上,Medium题要求思路清晰、代码无Bug、复杂度分析到位。Android岗集中在树、栈/队列、贪心和字符串匹配,不考图论和高级DP,但手写代码要能跑通。

今天8道题覆盖美团算法核心考点,每道给出思路+代码+复杂度。

Q1:二叉树的前中后序遍历?迭代怎么写?

递归写法简单:前序(根→左→右)、中序(左→根→右)、后序(左→右→根)。三行代码搞定。

迭代写法(面试常考):用栈模拟递归。

前序迭代:根入栈,循环弹栈处理 → 右子入栈 → 左子入栈(栈后进先出,左子先处理)。

List<Integer> preorder(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    Stack<TreeNode> stack = new Stack<>();
    if (root != null) stack.push(root);
    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        result.add(node.val);
        if (node.right != null) stack.push(node.right);
        if (node.left != null) stack.push(node.left);
    }
    return result;
}

中序迭代:一路向左入栈,到头弹栈处理,转向右子树。

追问:中序遍历BST结果有序(从小到大),验证BST只需中序遍历看是否递增。BST查找O(log n),退化链表时O(n)。

Q2:层序遍历怎么按层输出?

用队列BFS。关键:每层处理前先记录队列当前size,循环size次弹出处理,这样就知道哪些节点在同一层。

List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> result = new ArrayList<>();
    Queue<TreeNode> queue = new LinkedList<>();
    if (root != null) queue.offer(root);
    while (!queue.isEmpty()) {
        int size = queue.size();
        List<Integer> level = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            TreeNode node = queue.poll();
            level.add(node.val);
            if (node.left != null) queue.offer(node.left);
            if (node.right != null) queue.offer(node.right);
        }
        result.add(level);
    }
    return result;
}

追问:二叉树最大深度怎么求?BFS层序遍历的层数就是最大深度。或递归:maxDepth = 1 + max(maxDepth(left), maxDepth(right))。时间O(n)空间O(h)。

Q3:用栈实现队列?用队列实现栈?

栈实现队列:两个栈。stack1用于push,stack2用于pop/peek。pop时如果stack2为空,把stack1全部倒入stack2(顺序反转),再从stack2弹出。均摊O(1)。

class MyQueue {
    Stack<Integer> s1 = new Stack<>(), s2 = new Stack<>();
    void push(int x) { s1.push(x); }
    int pop() {
        if (s2.isEmpty()) while (!s1.isEmpty()) s2.push(s1.pop());
        return s2.pop();
    }
}

队列实现栈:两个队列。push加入q1,pop时把q1前n-1个元素倒入q2,弹出q1末个元素,交换q1和q2。pop是O(n)。

追问:Android里栈的用途?Activity返回栈、Fragment addToBackStack、方法调用栈。队列呢?Handler的MessageQueue、线程池BlockingQueue。

Q4:最小栈怎么实现?

支持push/pop/top/getMin都是O(1)的栈。

方案:两个栈。data栈存数据,min栈存当前最小值。push时data正常push,min栈push(min(新值, min栈顶))。pop时两个栈同时pop。getMin返回min栈顶。

class MinStack {
    Stack<Integer> data = new Stack<>(), min = new Stack<>();
    void push(int x) {
        data.push(x);
        min.push(min.isEmpty() ? x : Math.min(x, min.peek()));
    }
    void pop() { data.pop(); min.pop(); }
    int top() { return data.peek(); }
    int getMin() { return min.peek(); }
}

追问:能用一个栈吗?可以——每个元素存value和当前min的pair,或存差值(当前值-min),空间更省但注意溢出。

Q5:贪心算法——区间调度问题

问题:给一组区间[start, end],选最多互不重叠的区间。

贪心策略:按结束时间排序,依次选不重叠区间。每次选结束最早的给后面留最多空间。

int maxIntervals(int[][] intervals) {
    Arrays.sort(intervals, (a, b) -> a[1] - b[1]);
    int count = 1, end = intervals[0][1];
    for (int i = 1; i < intervals.length; i++) {
        if (intervals[i][0] >= end) { count++; end = intervals[i][1]; }
    }
    return count;
}

时间O(n log n)排序,空间O(1)。

追问:贪心正确性——选结束最早的区间不影响后面可选区间。最优解没选结束最早的可以替换,解不会变差。

Q6:字符串匹配——KMP算法

暴力匹配:O(m*n)。文本串每个位置跟模式串逐字符比较,不匹配回退。

KMP:O(m+n)。next数组(前缀表)记录模式串每个位置的最长相等前后缀长度。匹配失败时不回退文本串指针,根据next数组跳过已知匹配的前缀。

next数组构建:双指针i遍历模式串,j指向当前最长前缀末尾。next[i] = pattern[0..i]的最长相等前后缀长度。

Android关联:Java的String.indexOf用朴素匹配(短字符串够用),大文本搜索用KMP或Boyer-Moore。

追问:Rabin-Karp用滚动哈希——hash相等才逐字符比较,平均O(n)最坏O(mn)。适合多模式匹配场景。

Q7:字符串反转和回文判断

反转字符串:双指针头尾交换。O(n)时间O(1)空间。

判断回文:双指针从两端向中间比较,跳过非字母数字字符,忽略大小写。遇到不匹配返回false,全部匹配返回true。O(n)时间O(1)空间。

追问:最长回文子串?中心扩展法——每个字符和字符间作为中心向两边扩展,记录最长。O(n²)时间O(1)空间。Manacher O(n)面试一般不考。

Q8:算法面试怎么准备?

刷题顺序:按类型——树→栈/队列→贪心→字符串→DP→二分。每类型10-15题。先Easy打基础再Medium练速度。Hard看时间,Android岗不强制。

面试技巧:确认题意 → 讲思路(不闷头写)→ 边写边讲 → 手动跑测试 → 分析复杂度。

常见错误:忘边界条件(空输入/单元素)、变量名太短易混、不测试就说没问题。


面试Tips:美团算法二叉树考前中后序迭代写法和层序BFS。栈/队列考互相实现和最小栈。贪心考区间调度(按结束时间排序)。字符串考KMP思路和回文判断。准备美团算法刷LeetCode Hot 100的树/栈/贪心/字符串分类就够。面试时讲思路比闷头写更重要——面试官想看你的思考过程。

下一篇进入Kotlin专项——协程异常处理、Channel与Flow、Kotlin编译器插件、KSP。


面试被考过KMP的同学评论区举个手,你能手写next数组吗?

本系列连载中,关注不迷路,下一篇:美团中级Android(Kotlin专项)面试真题

系列简介:Android大厂面经连载,覆盖字节跳动、腾讯、阿里、美团等40+企业,从初级到架构师全岗位覆盖。每篇文章包含真实面试题+详细答案+代码示例,帮你拿到大厂Offer。