2018JAVA成都岗---蚂蚁金服笔试部分面试题

下面题目是马海银(厥衡)大牛内推蚂蚁金服做的面试题。

源码已上传至我的GitHub:https://github.com/tangquanbin/structure

题目1:最小函数min()栈

1. 设计含最小函数min()、取出元素函数pop()、放入元素函数push()的栈AntMinStack,实现其中指定的方法
2. AntMinStack中数据存储使用Java原生的Stack,存储数据元素为int。请实现下面对应的方法,完善功能。
import java.util.Stack;

/**
 * 1:最小函数min()栈
 *
 * 1. 设计含最小函数min()、取出元素函数pop()、放入元素函数push()的栈AntMinStack,实现其中指定的方法
 * 2. AntMinStack中数据存储使用Java原生的Stack,存储数据元素为int。请实现下面对应的方法,完善功能。
 * @author tangquanbin
 * @date 2018/09/11 21:44
 */
public class AntMinStack {
    /**
     * 真正存放数据栈
     */
    public static Stack<Integer> stack = new Stack<>();

    /**
     * 存放最小数栈
     */
    public static Stack<Integer> minStack = new Stack<>();

    /**
     * push 放入元素
     * @param data
     */
    public void push(int data) {
        stack.push(data);
        if (minStack.size()==0||data<minStack.peek()){
            minStack.push(data);
        }else {
            minStack.push(minStack.peek());
        }
    }

    /**
     * pop 推出元素
     * @return
     * @throws Exception
     */
    public int pop() throws Exception {
        minStack.pop();
        return stack.pop();
    }

    /**
     * min 最小函数,调用该函数,可直接返回当前AntMinStack的栈的最小值
     *
     * @return
     * @throws Exception
     */
    public int min() throws Exception {
        return minStack.peek();
    }

    public static void main(String[] args){
        AntMinStack antMinStack = new AntMinStack();
        antMinStack.push(2);
        antMinStack.push(1);
        antMinStack.push(8);
        antMinStack.push(9);
        antMinStack.push(1);
        try {
            System.out.println("最小值:"+antMinStack.min());
            antMinStack.pop();
            antMinStack.pop();
            System.out.println("最小值:"+antMinStack.min());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

题目2:算数表达式

设计数据结构与算法,计算算数表达式,需要支持
  1. 基本计算,加减乘除,满足计算优先级 例如输入 3*0+3+8+9*1 输出20
  2. 括号,支持括号,例如输入 3+(3-0)*2 输出 9
  3. 假设所有的数字均为整数,无需考虑精度问题
要求:
1. 输入的表达式是字符串类型String。
2. 对于操作数要求不止一位,这里对字符串里面解析出操作数有要求。需要有从表达式里面解析出完整操作数的能力。
3. 代码结构要求具备一定的面向对象原则,能够定义出表达式,操作数,运算符等对象。
4. 提供基本的测试。
/**
 * 表达式
 *
 * @author tangquanbin
 * @date 2018/9/12 19:42
 */
public class Expression {

    /**
     * 表达式名字
     */
    private String name;

    /**
     * 表达式
     */
    private String expressionStr;

    /**
     * 表达式值
     */
    private int value;


    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getExpressionStr() {
        return expressionStr;
    }

    public void setExpressionStr(String expressionStr) {
        this.expressionStr = expressionStr;
    }

    public int getValue() {
        return value;
    }

    public void setValue(int value) {
        this.value = value;
    }

}

  

/**
 * 操作数
 * @author tangquanbin
 * @date 2018/9/12 19:43
 */
public class Operand {
    /**
     * 操作数值
     */
    private Integer operandValue;

    public Integer getOperandValue() {
        return operandValue;
    }

    public void setOperandValue(Integer operandValue) {
        this.operandValue = operandValue;
    }
}

  

/**
 * 运算符
 *
 * @author tangquanbin
 * @date 2018/9/12 19:43
 */
public class Operator {
    /**
     * 运算符符号
     */
    private char operatorName;

    public char getOperatorName() {
        return operatorName;
    }

    public void setOperatorName(char operatorName) {
        this.operatorName = operatorName;
    }

}

  

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 计算工具
 * @author tangquanbin
 * @date 2018/9/13 14:35
 */
public class CalculatorUtil {
    /**
     * 加
     */
    private static final String ADD = "+";
    /**
     * 减
     */
    private static final String SUBTRACT = "-";
    /**
     * 乘
     */
    private static final String MULTIPLICATION = "*";
    /**
     * 除
     */
    private static final String DIVISION = "/";
    /**
     * 左括号
     */
    private static final String LEFT_PARENTHESIS = "(";
    /**
     * 右括号
     */
    private static final String RIGHT_PARENTHESIS = ")";


    /**
     *
     * 提供给外部的计算方法
     *
     * @param expression 后缀表达式
     * @return 计算结果
     */
    public static int calculation(Expression expression) throws Exception {
        List<String> list = getPostfix(expression);
        Stack<Integer> calculationStack = new Stack<>();
        Integer operandRight;
        Integer operandLeft;
        for (String item : list) {
            if (ADD.equals(item)) {
                operandRight  = calculationStack.pop();
                operandLeft = calculationStack.pop();
                calculationStack.push(operandLeft + operandRight);
            } else if (SUBTRACT.equals(item)) {
                operandRight  = calculationStack.pop();
                operandLeft = calculationStack.pop();
                calculationStack.push(operandLeft - operandRight);
            } else if (MULTIPLICATION.equals(item)) {
                operandRight  = calculationStack.pop();
                operandLeft = calculationStack.pop();
                calculationStack.push(operandLeft * operandRight);
            } else if (DIVISION.equals(item)) {
                operandRight  = calculationStack.pop();
                operandLeft = calculationStack.pop();
                calculationStack.push(operandLeft / operandRight);
            } else {
                calculationStack.push(Integer.parseInt(item));
            }
        }

        return calculationStack.pop();
    }

    /**
     * 判断字符为运算符(+,-,*,/)
     *
     * @param c 输入字符
     * @return
     */
    private static boolean isOperator(char c) {

        return ADD.equals(String.valueOf(c)) || SUBTRACT.equals(String.valueOf(c)) ||
                MULTIPLICATION.equals(String.valueOf(c)) || DIVISION.equals(String.valueOf(c));
    }

    /**
     * 返回的是运算符的优先级
     *
     * @param operator
     * @return
     */
    private static int priority(Operator operator) {
        char operatorName = operator.getOperatorName();
        if (ADD.equals(String.valueOf(operatorName)) || SUBTRACT.equals(String.valueOf(operatorName))) {
            return 1;
        } else if (MULTIPLICATION.equals(String.valueOf(operatorName)) || DIVISION.equals(String.valueOf(operatorName))) {
            return 2;
        } else {
            return 0;
        }
    }

    /**
     * 通过表达式获得后缀表达式
     *
     * @param expression
     * @return
     */
    private static List<String> getPostfix(Expression expression) throws Exception {
        /**
         * 操作符栈
         */
        Stack<Operator> operatorStack = new Stack<>();

        /**
         * 存放后缀表达式
         */
        List<String> operandList = new ArrayList<>();

        String expressionStr = expression.getExpressionStr();
        for (int i = 0; i < expressionStr.length(); i++) {
            char oneChar = expressionStr.charAt(i);

            Operator operator = new Operator();
            operator.setOperatorName(oneChar);

            //遇到操作数:直接输出(添加到后缀表达式中)
            if (Character.isDigit(oneChar)) {
                int num = oneChar - '0';
                while (i + 1 < expressionStr.length() && Character.isDigit(expressionStr.charAt(i + 1))) {
                    num = num * 10 + expressionStr.charAt(i + 1) - '0';
                    i++;
                }
                operandList.add(String.valueOf(num));
            } else if (LEFT_PARENTHESIS.equals(String.valueOf(oneChar))) {
                //遇到左括号:将其入栈
                operatorStack.push(operator);
            } else if (RIGHT_PARENTHESIS.equals(String.valueOf(oneChar))) {
                //遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
                while (!LEFT_PARENTHESIS.equals(String.valueOf(operatorStack.peek().getOperatorName()))) {
                    operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
                }
                //然后弹出左括号
                operatorStack.pop();
            } else if (isOperator(oneChar)) {
                //遇到运算符
                //栈为空时,直接入栈
                if (operatorStack.isEmpty()) {
                    operatorStack.push(operator);
                } else {
                    // 如果读入的操作符为非")"且优先级比栈顶元素的优先级高或一样
                    if (priority(operatorStack.peek()) < priority(operator)) {
                        operatorStack.push(operator);
                    } else if (priority(operatorStack.peek()) >= priority(operator)) {
                        operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
                        operatorStack.push(operator);
                    }
                }
            }
        }

        //最终将栈中的元素依次出栈。
        while (!operatorStack.isEmpty()) {
            operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
        }
        System.out.println(operandList);
        return operandList;
    }

}

  测试类

/**
 * @author tangquanbin
 * @date 2018/9/13 11:49
 */
public class Test {


    public static void main(String[] args) {
        Expression expression = new Expression();
        expression.setExpressionStr("4 +(13 - 5)");
        try {
            System.out.println(CalculatorUtil.calculation(expression));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

  

题目3:提供一个懒汉模式的单实例类实现,并满足如下要求:

    1.考虑线程安全。
    2.基于junit提供测试代码,模拟并发,测试线程安全性,给出对应的断言。
/**
 * 3:提供一个懒汉模式的单实例类实现,并满足如下要求:
 *     1.考虑线程安全。
 *     2.基于junit提供测试代码,模拟并发,测试线程安全性,给出对应的断言。
 * @author tangquanbin
 * @date 2018/9/12 19:04
 */
public class Singleton {

    private Singleton(){

    }

    public static Singleton getInstance(){
        return  SingletonHelper.instance;
    }

    /**
     * 静态内部内
     */
    private static class SingletonHelper{
        private static final Singleton instance = new Singleton();
    }

}

  Junit断言测试

import com.good.good.study.singleton.Singleton;
import org.junit.Test;

import java.util.concurrent.CountDownLatch;

import static org.junit.Assert.assertEquals;

/**
 * @author tangquanbin
 * @date 2018/9/13 15:01
 */
public class JunitTest {

    private CountDownLatch latch = new CountDownLatch(3);

    @Test
    public void testSingleton(){
        final String hashCode = String.valueOf(Singleton.getInstance().hashCode());
        for (int i=0;i<200;i++) {
            Thread thread = new Thread() {
                @Override
                public void run() {
                    assertEquals(hashCode,String.valueOf(Singleton.getInstance().hashCode()));
                }
            };
            thread.start();
        }

        try {
            latch.await(); // 主线程等待
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

  

 

猜你喜欢

转载自www.cnblogs.com/tangquanbin/p/9691958.html