棧經典問題(附部分代碼和測試)

棧經典問題

  • 括號匹配
  • 中綴轉後綴表達式
  • 最小棧
  • 判迴文
  • 反轉棧
  • 在數組中實現2個棧
  • 擴展1:在數組中實現3個棧
  • 擴展2:在數組中實現n個棧
  • 算跨度
  • 擴展1:最大矩形
  • 棧排序

注意:算跨度問題,不管我怎麼算,都沒有算出來,最後放棄了。

附:
棧實現

import java.util.HashMap;
import java.util.Map;

public class LLStack<T> {
    private LLNode head = new LLNode();

    private class LLNode<T> {
        T data;
        LLNode next;

        public LLNode() {
        }

        public LLNode(T data) {
            this.data = data;
        }

        public LLNode(T data, LLNode next) {
            this.data = data;
            this.next = next;
        }
    }

    private static class EmpytStackException extends RuntimeException {
        public EmpytStackException(String message) {
            super(message);
        }
    }

    public T top() {
        checkEmpty();
        return (T) head.next.data;
    }

    public void push(T data) {
        head.next = new LLNode<T>(data, head.next);
    }

    public T pop() {
        checkEmpty();
        LLNode t = head.next;
        head.next = t.next;
        t.next = null;
        return (T) t.data;
    }

    private void checkEmpty() {
        if (head.next == null) {
            throw new EmpytStackException("Stack empty");
        }
    }

    public boolean isEmpty() {
        return head.next == null;
    }

    public void deleteStack() {
        while (head.next != null) {
            LLNode t = head.next;
            head.next = t.next;
            t.next = null;
        }
    }

    public int size(){
        LLNode it = head.next;
        int count = 0;
        while(it!=null){
            count++;
            it = it.next;
        }
        return count;
    }

    public T get(int index){
        if(index>size()-1){
            throw new IndexOutOfBoundsException(index+"");
        }
        LLNode it = head.next;
        for(int i=0;i<index;i++){
            it = it.next;
        }
        return (T) it.data;
    }
    @Override
    public String toString() {
        StringBuilder msg = new StringBuilder();
        LLNode<T> it = head.next;
        while (it != null) {
            msg.append(it.data);
            if (it.next != null) {
                msg.append("->");
            }
            it = it.next;
        }
        return msg.toString();
    }
    public static LLStack<Integer> fromArray(int[] data){
        LLStack<Integer> stack = new LLStack<>();
        for(int it:data){
            stack.push(it);
        }
        return stack;
    }
    public static boolean isBracketsMatch(String s) {
        LLStack<Character> stack = new LLStack<>();
        char[] buf = s.toCharArray();
        Map<Character, Character> map = new HashMap<>();
        map.put(')', '(');
        map.put(']', '[');
        map.put('}', '{');
        for (char ch : buf) {
            if (ch == '(' || ch == '[' || ch == '{') {
                stack.push(ch);
            } else if (ch == ')' || ch == ']' || ch == '}') {
                Character target = map.get(ch);
                if (stack.isEmpty()) return false;
                Character actual = stack.pop();
                if (target != actual) return false;
            }
        }
        return stack.isEmpty();
    }

    public static String convertInfix2SuffixExpression(String expr) {
        StringBuilder result = new StringBuilder();
        Map<Character, Integer> priorityMap = new HashMap<>();
        for (char ch : "()[].".toCharArray()) priorityMap.put(ch, 17);
        for (char ch : "*/%".toCharArray()) priorityMap.put(ch, 13);
        for (char ch : "+-".toCharArray()) priorityMap.put(ch, 12);
        LLStack<Character> operatorStack = new LLStack<>();
        for (char ch : expr.toCharArray()) {
            // 如果是一個操作數
            if (!priorityMap.containsKey(ch)) {
                result.append(ch);
            }
            // 如果是右括號
            else if (ch == ')') {
                if (operatorStack.isEmpty()) continue;
                Character topOperator = operatorStack.top();
                if (topOperator == '(') {
                    operatorStack.pop();
                    continue;
                }
                result.append(operatorStack.pop());
            } else {
                // 其他情況
                do {
                    if (operatorStack.isEmpty() ||
                            operatorStack.top() == '(' ||
                            priorityMap.get(ch) > priorityMap.get(operatorStack.top())
                    ) {
                        operatorStack.push(ch);
                        break;
                    }
                    result.append(operatorStack.pop());
                } while (true);
            }

        }
        while (!operatorStack.isEmpty()) {
            Character popOperator = operatorStack.pop();
            if (popOperator != ')' && popOperator != '(') {
                result.append(popOperator);
            }
        }
        return result.toString();
    }

    public static Integer calculateSuffixExpression(String expr){
        LLStack<String> operandStack = new LLStack<>();
        for(char ch:expr.toCharArray()){
            if(ch=='*' || ch=='/' || ch=='+' || ch=='-'){
                Integer operand1 = Integer.valueOf(operandStack.pop()+"");
                Integer operand2 = Integer.valueOf(operandStack.pop()+"");
                int result = 0;
                switch(ch){
                    case '*':{
                        result = operand1 * operand2;
                        break;
                    }
                    case '/':{
                        result = operand2 / operand1;
                        break;
                    }
                    case '+':{
                        result = operand1 + operand2;
                        break;
                    }
                    case '-':{
                        result = operand2 - operand1;
                        break;
                    }
                    default:{

                    }
                }
                operandStack.push(String.valueOf(result));
            }else{
                operandStack.push(ch+"");
            }
        }
        return Integer.valueOf(operandStack.pop());
    }

    public static boolean isPalindrome(String s){
        LLStack<Character> stack = new LLStack<>();
        boolean flag = false;
        for(char ch:s.toCharArray()){
            if(flag){
                if(stack.isEmpty() || ch!=stack.pop()){
                    return false;
                }
            }else{
                if(ch!='X'){
                    stack.push(ch);
                }else{
                    flag = true;
                }
            }
        }
        return stack.isEmpty();
    }

    public static LLStack reverseStack(LLStack<Integer> stack){
        if(stack.isEmpty()) return stack;
        Integer temp = stack.pop();
        reverseStack(stack);
        insertAtBottom(stack,temp);
        return stack;
    }
    private static void insertAtBottom(LLStack<Integer> stack, int data){
        if(stack.isEmpty()){
            stack.push(data);
            return;
        }
        Integer temp = stack.pop();
        insertAtBottom(stack,data);
        stack.push(temp);
    }
    public static int[] findingSpans_v1(int[] inputArray){
        int[] spans = new int[inputArray.length];
        for(int i=0;i<inputArray.length;i++){
            int span = 1;
            int j = i - 1;
            while(j>=0 && inputArray[j] <= inputArray[j+1]){
                span++;
                j--;
            }
            spans[i] = span;
        }
        return spans;
    }
    public static int[] findingSpans(int[] inputArray){
        int[] spans = new int[inputArray.length];
        LLStack<Integer> stack = new LLStack<>();
        int p = 0;
        for(int i=0;i<inputArray.length;i++){
            while(!stack.isEmpty() &&
                    inputArray[i] > inputArray[stack.top()]){
                stack.pop();
            }
            if(stack.isEmpty()) p = -1;
            else p = stack.pop();
            spans[i] = i - p;
            stack.push(i);
        }
        return spans;
    }
    public static LLStack<Integer> sort(LLStack<Integer> s){
        LLStack<Integer> r = new LLStack<Integer>();
        while(!s.isEmpty()){
            int tmp = s.pop();
            while(!r.isEmpty() && r.top() < tmp){
                s.push(r.pop());
            }
            r.push(tmp);
        }
        return r;
    }
}

測試代碼

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.Arrays;

import static org.junit.Assert.*;

public class LLStackTest {

    @Before
    public void setUp() throws Exception {
    }

    @Test
    public void testIsBracketsMatch() {
        Object[][] data = new Object[][]{
                {"(A+B)+(C-D)", true},
                {"((A+B)+(C-D)", false},
                {"((A+B)+[C-D])", true},
                {"((A+B)+[C-D]}", false},
        };
        for (Object[] it : data) {
            Assert.assertEquals((String) it[0], it[1], LLStack.isBracketsMatch((String) it[0]));
        }
    }

    @Test
    public void testConvertInfix2SuffixExpression() {
        String[][] data = new String[][]{
                {"A", "A"},
                {"(A)", "A"},
                {"A+B", "AB+"},
                {"(A+B)", "AB+"},
                {"A+B+C", "AB+C+"},
                {"A+B+C+D", "AB+C+D+"},
                {"A+B*C+D", "ABC*+D+"},
                {"A+B*(C+D)", "ABCD+*+"},
                {"(A+B)+(C-D)", "AB+CD-+"},
                {"(A+B)+((C-D))", "AB+CD-+"},
                {"2+3*4", "234*+"}
        };
        for (String[] it : data) {
            Assert.assertEquals(it[0], it[1], LLStack.convertInfix2SuffixExpression(it[0]));
        }
    }

    @Test
    public void testCalculateSuffixExpression() {
        Object[][] data = new Object[][]{
                {"234*+", 14},
                {"123*+5-", 2},
                {"42/", 2},
        };
        for (Object[] it : data) {
            Assert.assertEquals((String) it[0], it[1], LLStack.calculateSuffixExpression((String) it[0]));
        }
    }

    @Test
    public void testIsPalindrome() {
        Object[][] data = new Object[][]{
                {"ababaXababa", true},
                {"babaXababa", false},
                {"ababaXabab", false},
        };
        for (Object[] it : data) {
            Assert.assertEquals((String) it[0], it[1], LLStack.isPalindrome((String) it[0]));
        }
    }

    @Test
    public void testReverseStack() {
        Object[][] data = new Object[][]{
                {LLStack.fromArray(new int[]{}), ""},
                {LLStack.fromArray(new int[]{1}), "1"},
                {LLStack.fromArray(new int[]{1, 2}), "1->2"},
                {LLStack.fromArray(new int[]{1, 2, 3}), "1->2->3"},
        };
        for (Object[] it : data) {
            Assert.assertEquals(it[0].toString(), LLStack.reverseStack((LLStack<Integer>) it[0]).toString(), it[1]);
        }
    }

    /**
     * 有問題
     */
    @Test
    public void testFindingSpans() {
        Object[][] data = new Object[][]{
//                {new int[]{1, 1}, new int[]{6, 3}},
//                {new int[]{1, 1, 2}, new int[]{6, 3, 4}},
//                {new int[]{1, 1, 2, 3}, new int[]{6, 3, 4, 5}},
//                {new int[]{3, 2, 1}, new int[]{1, 1, 1}},
//                {new int[]{3, 2, 2, 1}, new int[]{1, 1, 2, 1}},
                {new int[]{1, 3, 2, 1, 1}, new int[]{6, 3, 4, 5, 2}},
        };
        for (Object[] it : data) {
            int[] result = LLStack.findingSpans((int[]) it[1]);
            Assert.assertEquals(Arrays.toString((int[]) it[1]), Arrays.toString((int[]) it[0]), Arrays.toString(result));

        }

    }

    @Test
    public void testFindingSpans_v1() {
        int[] result = LLStack.findingSpans_v1(new int[]{6, 3, 4, 5, 2});
        Assert.assertEquals(Arrays.toString(new int[]{1, 1, 2, 3, 1}), Arrays.toString(result));

    }
    @Test
    public void testSort(){
        Object[][] data = new Object[][]{
                {"1",new int[]{1}},
                {"1->2",new int[]{1,2}},
                {"1->2->3",new int[]{1,3,2}},
        };
        for(Object[] it:data){
            LLStack<Integer> s = LLStack.fromArray((int[])it[1]);
            LLStack<Integer> result = LLStack.sort(s);
            Assert.assertEquals(Arrays.toString((int[])it[1]),it[0],result.toString());
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章