1. 程式人生 > >2018JAVA成都崗---螞蟻金服筆試部分面試題

2018JAVA成都崗---螞蟻金服筆試部分面試題

junit 輸出 https study 安全性 ons 滿足 tps one

下面題目是馬海銀(厥衡)大牛內推螞蟻金服做的面試題。

源碼已上傳至我的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();
        }

    }
}

  

2018JAVA成都崗---螞蟻金服筆試部分面試題