回复: 9
跳转到指定楼层
上一主题 下一主题
收起左侧

FB实习二面跪经

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
刚刚的FB实习二面跪经,运气不太好,之前地理的面经,LC的tag都做了。没想到来了一个后来才发现是而而思 计算器的变种,in
您好!
本帖隐藏的内容需要积分高于 188 才可浏览
您当前积分为 0。
使用VIP即刻解锁阅读权限或查看其他获取积分的方式
游客,您好!
本帖隐藏的内容需要积分高于 188 才可浏览
您当前积分为 0。
VIP即刻解锁阅读权限查看其他获取积分的方式
Unlock interview details and practice with AI
Curated Interview Questions from Top Companies

实习给个这么难的,哎。还是得好好刷题吧,200道还是不够。

评分

参与人数 4大米 +27 收起 理由
AnthonyNeu + 5 给你点个赞!
sparrow52 + 10 很有用的信息!
flyMontain + 2 很有用的信息!
xh_pku + 10 很有用的信息!

查看全部评分


上一篇:纯存储很尴尬的跪经
下一篇:热乎乎的巴克莱oa

本帖被以下淘专辑推荐:

🔗
dingshilun 2018-1-10 07:42:50 | 只看该作者
全局:
用两个栈进行计算,一个存储数字一个存储符号,入栈的符号优先级低于栈顶符号时,将所有高于的符号出栈然后计算,遇到反括号就不停出栈计算直到遇到正括号。 可以把这个过程想象成一个简单的语法树。。
回复

使用道具 举报

🔗
Liddy_L 2018-1-10 08:56:57 | 只看该作者
全局:
继续找吧,LZ这么认真一定能找到的。
回复

使用道具 举报

全局:
顺序扫string,maintain一个toAdd和toMultiply,toAdd一开始是0,toMultiply一开始是1,具体更新方法和lc 282 (Expression add operator)一样。关于括号,遇到开括号直接递归call,遇到反括号直接return当前结果
回复

使用道具 举报

全局:
递归后得想办法更新当前string的index,可以用global variable
回复

使用道具 举报

🔗
alicesm 2018-1-10 23:54:57 | 只看该作者
全局:
会有好运气的!
楼主是店面还是uday呀!
回复

使用道具 举报

🔗
1451427216 2018-1-11 00:12:08 | 只看该作者
全局:
这个题lintcode上有,算是很难的题了,楼主加油~
回复

使用道具 举报

🔗
本地农民 2018-1-11 00:43:56 | 只看该作者
全局:
这个确实是hard, 保持一个increasing  stack, 对不同符号定义不同优先级。具体去lintcode 看看
回复

使用道具 举报

🔗
magicsets 2018-1-11 06:22:36 | 只看该作者
全局:
这边有一份支持“自定义操作符”的代码,LZ可以参考学习一下...

第13到22行的代码写出来是可以impress住面试官的,基本上所有Calculator的变形题都可以通过改这几行处理(如果要处理浮点类型则要稍微改一下nextNumber()函数)。

  1. import java.util.ArrayList;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.Map;
  5. import java.util.Stack;

  6. public class Main {
  7.   public static void main(String[] args) {
  8.     Calculator calc = new Calculator();

  9.     // 中间的数字是优先级(precedence),数字越小优先级越高
  10.     // 这里限定二元运算符是left associative,一元运算符是right associative
  11.     calc.registerOperation("+", 500, (a, b) -> a + b);
  12.     calc.registerOperation("-", 500, (a, b) -> a - b);
  13.     calc.registerOperation("*", 400, (a, b) -> a * b);
  14.     calc.registerOperation("/", 400, (a, b) -> a / b);
  15.     calc.registerOperation("**", 200, (a, b) -> (int) Math.pow(a, b));
  16.     calc.registerOperation("-", 100, (a) -> -a);

  17.     calc.registerFunction("abs", (int ...a) -> Math.abs(a[0]));
  18.     calc.registerFunction("min", (int ...a) -> Math.min(a[0], a[1]));
  19.     calc.registerFunction("max", (int ...a) -> Math.max(a[0], a[1]));

  20.     System.out.println(calc.evaluate("1 + 2 * 3 ** abs(6 - 3 * 3) + (-8) / (-2)"));
  21.     System.out.println(calc.evaluate("min(-3 * 2, -4) * max(5, 6)"));
  22.   }
  23. }

  24. /******************************************************************************
  25. 样例:使用下面的Solution类可以通过LeetCode 224

  26. class Solution {
  27.   private static Calculator calc = new Calculator();
  28.   static {
  29.     calc.registerOperation("+", 500, (a, b) -> a + b);
  30.     calc.registerOperation("-", 500, (a, b) -> a - b);
  31.     calc.registerOperation("-", 100, (a) -> -a);
  32.   }

  33.   public int calculate(String s) {
  34.     return calc.evaluate(s);
  35.   }
  36. }

  37. ******************************************************************************/

  38. /******************************************************************************
  39. 样例:使用下面的Solution类可以通过LeetCode 227

  40. class Solution {
  41.   private static Calculator calc = new Calculator();
  42.   static {
  43.     calc.registerOperation("+", 500, (a, b) -> a + b);
  44.     calc.registerOperation("-", 500, (a, b) -> a - b);
  45.     calc.registerOperation("*", 400, (a, b) -> a * b);
  46.     calc.registerOperation("/", 400, (a, b) -> a / b);
  47.     calc.registerOperation("-", 100, (a) -> -a);
  48.   }

  49.   public int calculate(String s) {
  50.     return calc.evaluate(s);
  51.   }
  52. }

  53. ******************************************************************************/

  54. class Calculator {
  55.   private Map<String, OperationInfo<UnaryOperation>> unaryOperations;
  56.   private Map<String, OperationInfo<BinaryOperation>> binaryOperations;
  57.   private Map<String, Function> functions;

  58.   public Calculator() {
  59.     this.unaryOperations =
  60.         new HashMap<String, OperationInfo<UnaryOperation>>();
  61.     this.binaryOperations =
  62.         new HashMap<String, OperationInfo<BinaryOperation>>();
  63.     this.functions = new HashMap<String, Function>();
  64.   }

  65.   // 注册一个一元运算符
  66.   public void registerOperation(String operator, int precedence,
  67.                                 UnaryOperation operation) {
  68.     unaryOperations.put(
  69.         operator, new OperationInfo<UnaryOperation>(precedence, operation));
  70.   }

  71.   // 注册一个二元运算符
  72.   public void registerOperation(String operator, int precedence,
  73.                                 BinaryOperation operation) {
  74.     binaryOperations.put(
  75.         operator, new OperationInfo<BinaryOperation>(precedence, operation));
  76.   }

  77.   // 注册一个函数
  78.   public void registerFunction(String name, Function function) {
  79.     functions.put(name, function);
  80.   }

  81.   // 调用Executor对表达式进行计算
  82.   public int evaluate(String expression) {
  83.     CalculatorExecutor executor =
  84.         new CalculatorExecutor(unaryOperations, binaryOperations,
  85.                                functions, expression);
  86.     return executor.run();
  87.   }
  88. }


  89. // 对一元运算符的抽象
  90. interface UnaryOperation {
  91.   public int apply(int operand);
  92. }

  93. // 对二元运算符的抽象
  94. interface BinaryOperation  {
  95.   public int apply(int operand1, int operand2);
  96. }

  97. // 对函数的抽象
  98. interface Function {
  99.   public int apply(int ...operands);
  100. }


  101. // 用于打包operation和对应的precedence信息的小类
  102. class OperationInfo<OpType> {
  103.   public final int precedence;
  104.   public final OpType operation;
  105.   public OperationInfo(int precedence, OpType operation) {
  106.     this.precedence = precedence;
  107.     this.operation = operation;
  108.   }
  109. }

  110. // LL(1) Recursive Descent Syntax Directed Translator
  111. class CalculatorExecutor {
  112.   private final Map<String, OperationInfo<UnaryOperation>> unaryOperations;
  113.   private final Map<String, OperationInfo<BinaryOperation>> binaryOperations;
  114.   private final Map<String, Function> functions;

  115.   private final String stream;
  116.   private int position;

  117.   // 词法部分也合并到这个类里了
  118.   private enum TokenType {
  119.     INTEGER,
  120.     NAME,
  121.     OPERATOR,
  122.     LPAREN,
  123.     RPAREN,
  124.     COMMA,
  125.     EOS,
  126.     ERROR
  127.   }

  128.   private class Token {
  129.     public final TokenType type;
  130.     public final Object payload;
  131.     public final int columnNumber;
  132.     public Token(TokenType type, int columnNumber) {
  133.       this(type, columnNumber, null);
  134.     }
  135.     public Token(TokenType type, int columnNumber, Object payload) {
  136.       this.type = type;
  137.       this.payload = payload;
  138.       this.columnNumber = columnNumber;
  139.     }
  140.   }

  141.   private Stack<Token> tokens;

  142.   public CalculatorExecutor(
  143.       Map<String, OperationInfo<UnaryOperation>> unaryOperations,
  144.       Map<String, OperationInfo<BinaryOperation>> binaryOperations,
  145.       Map<String, Function> functions,
  146.       String stream) {
  147.     this.unaryOperations = unaryOperations;
  148.     this.binaryOperations = binaryOperations;
  149.     this.functions = functions;
  150.     this.stream = stream;
  151.     this.position = 0;
  152.     this.tokens = new Stack<Token>();
  153.   }

  154.   public int run() {
  155.     int value = evalExpr(Integer.MAX_VALUE);
  156.     passNextToken(TokenType.EOS);
  157.     return value;
  158.   }

  159.   private int evalExpr(int precedence) {
  160.     int value = evalFactor(precedence);

  161.     while (hasNextToken(TokenType.OPERATOR)) {
  162.       Token token = nextToken();
  163.       OperationInfo<BinaryOperation> info =
  164.           binaryOperations.get((String)token.payload);
  165.       if (info == null || info.precedence >= precedence) {
  166.         pushBack(token);
  167.         break;
  168.       }
  169.       value = info.operation.apply(value, evalExpr(info.precedence));
  170.     }
  171.     return value;
  172.   }

  173.   private int evalFactor(int precedence) {
  174.     Token token = nextToken();

  175.     if (token.type == TokenType.INTEGER) {
  176.       return (Integer)token.payload;
  177.     }

  178.     if (token.type == TokenType.OPERATOR) {
  179.       OperationInfo<UnaryOperation> info =
  180.           unaryOperations.get((String)token.payload);
  181.       if (info == null || info.precedence > precedence) {
  182.         error(token);
  183.       }
  184.       return info.operation.apply(evalExpr(info.precedence));
  185.     }

  186.     if (token.type == TokenType.NAME) {
  187.       Function func = functions.get((String)token.payload);
  188.       if (func == null) {
  189.         error(token);
  190.       }
  191.       ArrayList<Integer> args = new ArrayList<Integer>();
  192.       passNextToken(TokenType.LPAREN);
  193.       while (!hasNextToken(TokenType.RPAREN)) {
  194.         args.add(evalExpr(Integer.MAX_VALUE));
  195.         if (!hasNextToken(TokenType.COMMA)) {
  196.           break;
  197.         }
  198.         nextToken();
  199.       }
  200.       passNextToken(TokenType.RPAREN);
  201.       return func.apply(args.stream().mapToInt(x -> x).toArray());
  202.     }

  203.     if (token.type == TokenType.LPAREN) {
  204.       int value = evalExpr(Integer.MAX_VALUE);
  205.       Token rp = nextToken();
  206.       if (rp.type != TokenType.RPAREN) {
  207.         error(token);
  208.       }
  209.       return value;
  210.     }

  211.     error(token);
  212.     return 0;
  213.   }

  214.   private boolean hasNextToken(TokenType ...expected) {
  215.     Token token = nextToken();
  216.     boolean status = Arrays.stream(expected).anyMatch(x -> x == token.type);
  217.     pushBack(token);
  218.     return status;
  219.   }

  220.   private void passNextToken(TokenType ...expected) {
  221.     Token token = nextToken();
  222.     if (!Arrays.stream(expected).anyMatch(x -> x == token.type)) {
  223.       error(token);
  224.     }
  225.   }

  226.   private void pushBack(Token token) {
  227.     tokens.add(token);
  228.   }

  229.   private Token nextToken() {
  230.     if (!tokens.isEmpty()) {
  231.       return tokens.pop();
  232.     }
  233.     while (position < stream.length() &&
  234.            Character.isWhitespace(stream.charAt(position))) {
  235.       ++position;
  236.     }

  237.     if (position >= stream.length()) {
  238.       return new Token(TokenType.EOS, position);
  239.     }

  240.     final int start = position;
  241.     final char ch = stream.charAt(position++);

  242.     switch (ch) {
  243.       case '(': return new Token(TokenType.LPAREN, start);
  244.       case ')': return new Token(TokenType.RPAREN, start);
  245.       case ',': return new Token(TokenType.COMMA, start);
  246.       default:  --position; break;
  247.     }

  248.     if (Character.isDigit(ch)) {
  249.       return nextNumber();
  250.     }
  251.     if (Character.isAlphabetic(ch)) {
  252.       return nextName();
  253.     }
  254.     return nextOperator();
  255.   }

  256.   private Token nextNumber() {
  257.     final int start = position;
  258.     while (position < stream.length() &&
  259.            Character.isDigit(stream.charAt(position))) {
  260.       ++position;
  261.     }
  262.     return new Token(TokenType.INTEGER, start,
  263.                      Integer.parseInt(stream.substring(start, position)));
  264.   }

  265.   private Token nextName() {
  266.     final int start = position;
  267.     while (position < stream.length() &&
  268.            Character.isAlphabetic(stream.charAt(position))) {
  269.       ++position;
  270.     }
  271.     return new Token(TokenType.NAME, start,
  272.                      stream.substring(start, position));
  273.   }

  274.   private Token nextOperator() {
  275.     final int start = position;
  276.     while (position < stream.length()) {
  277.       final char ch = stream.charAt(position);
  278.       if (Character.isWhitespace(ch) ||
  279.           Character.isDigit(ch) ||
  280.           Character.isAlphabetic(ch) ||
  281.           ch == '(' || ch == ')' || ch == ',') {
  282.         break;
  283.       }
  284.       ++position;
  285.     }
  286.     return new Token(TokenType.OPERATOR, start,
  287.                      stream.substring(start, position));
  288.   }

  289.   private void error(Token token) {
  290.     throw new RuntimeException(
  291.         "Syntax error: unexpected token at column " +
  292.         (token.columnNumber+1) + " -- " + token.type.name() +
  293.         (token.payload == null ? "" : " (" + token.payload.toString() + ")"));
  294.   }
  295. }
复制代码
回复

使用道具 举报

🔗
cxw111 2018-1-11 06:29:19 | 只看该作者
全局:
patpat,这题我记得pocketgems 喜欢考,还有一位大佬总结了所有的计算器变形来着。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表