拼多多二面笔试原题,15分钟没做出来,直接挂了。。。

1,025 阅读4分钟

这道题是 LeetCode 的第 32 题,难度为困难。一网友在拼多多的二面笔试中遇到这道题,不过很遗憾的是没做出来,结果直接挂了。拼多多现在也越来越像字节看齐了,面试专考难的。

一般来说一面能过说明技术都不算太差,结果一面过了挂在了二面的算法中,真的是不应该,我们来看下这题除了在拼多多的面试中出现,还有哪些大厂考过。

我们看到拼多多,华为,字节,腾讯,网易都考过这题,所以如果想要进大厂,最好把这题完全掌握。

图片

问题描述

来源:LeetCode第32题

难度:困难

给你一个只包含 '(' 和 ')' 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

示例 1:

输入:s = "(()"

输出:2

解释:最长有效括号子串是 "()"

示例 2:

输入:s = ")()())"

输出:4

解释:最长有效括号子串是 "()()"

使用栈解决

这题让求的是最长有效括号长度,一个有效的括号一定是满足下面两个条件:

  • 左括号和右括号的数量一定是相等的。
  • 在有效括号的任何位置左括号的数量一定是大于等于右括号的数量。

根据这两个特性我们可以使用栈来解决,栈中存放的是字符的下标,解决思路就是:

  • 如果遇到左括号我们就把他的下标压栈。
  • 如果遇到右括号,栈顶元素出栈,如果栈不为空说明出栈的元素和这个右括号匹配,我们需要计算他们的长度,保留最大值即可。如果栈为空,直接把这个右括号所在的下标压栈。

这里要注意如果给定的字符串从一开始就是有效的括号,比如 "()())"4 个符号是有效的括号,我们是没法计算他的长度的,因为第一个字符前面是没有字符的,所以我们默认第一个字符前面的下标是 -1 ,然后把他压栈,我们以 示例2 为例画个图来看下。

图片

最后再来看下代码:

public int longestValidParentheses(String s) {
    int max = 0;// 记录最大长度
    Stack<Integer> stack = new Stack<>();// 栈
    stack.push(-1);// 先把-1压栈
    for (int i = 0; i < s.length(); i++) {
        if (s.charAt(i) == '(') {
            stack.push(i);// 遇到左括号,下标压栈
        } else {
            stack.pop();// 遇到右括号,栈顶元素先出栈。
            if (stack.empty()) {
                // 如果栈为空,把这个右括号的下标压栈。
                stack.push(i);
            } else {// 计算长度,保存最大值。
                max = Math.max(max, i - stack.peek());
            }
        }
    }
    return max;
}

动态规划

再来看下动态规划该怎么解决,我们用 dp[i] 表示以是 s[i] 为结尾的最长有效括号长度,如果要计算 dp[i] 就会有下面几种情况:

  • i 个字符是左括号 "(" ,那么以他结尾的是构不成有效括号的,所以 dp[i]=0 ;
  • i 个字符是右括号 ")" ,那么以他结尾的是有可能构成有效括号的,所以还需要继续判断:
  1. 这里我们需要判断他前面的也就是第 i-1 个字符,如果第 i-1 个字符是左括号 "(" ,类似于 ……() ,那么最长有效括号就是第 i-2 个字符之前构成的 最长有效括号+2 ,也就是 dp[i]=dp[i-2]+2
  2. 如果第 i-1 个字符也是右括号 ")" ,类似于 ……((……)) ,如下图所示,我们还需要判断第 i -1- dp[i - 1] 个字符是否是左括号 "(" ,如果是 "(" ,那么递推公式是 dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2] ,这里 dp[i - dp[i - 1] - 2] 是第一个省略号构成的有效括号长度,这个不要忘了。

图片

public int longestValidParentheses(String s) {
    int max = 0;
    s = ")" + s;// 这里为了方便计算前面加个右括号
    int dp[] = new int[s.length()];
    for (int i = 2; i < s.length(); i++) {
        if (s.charAt(i) == ')') {
            // 递推公式
            if (s.charAt(i - 1) == '(') {
                dp[i] = dp[i - 2] + 2;
            } else if (s.charAt(i - dp[i - 1] - 1) == '(') {
                dp[i] = dp[i - 1] + 2 + dp[i - dp[i - 1] - 2];
            }
            max = Math.max(max, dp[i]);// 保存最大值
        }
    }
    return max;
}

笔者简介

博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解700多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注