算法练习 - 栈和队列(一)

算法练习 - 栈和队列(一)

1 实现栈

1.1 基于数组

public class StackTest {
    
    

    // 基于数组实现顺序栈
    public class ArrayStack {
    
    
        private int[] items; // 数组
        private int count; // 元素个数
        private int n; // 栈的大小

        public ArrayStack(int n) {
    
    
            this.items = new int[n];
            this.count = 0;
            this.n = n;
        }

        public boolean push(int item) {
    
    
            if (count == n) {
    
    
                // 栈已满,入栈失败
                return false;
            }
            items[count] = item;
            ++count;
            return true;
        }

        public int pop() {
    
    
            if (count == 0) {
    
    
                // 栈为空
                return -1;
            }
            int value = items[count - 1];
            --count;
            return value;
        }

        public int peek() {
    
    
            if (count == 0) {
    
    
                // 栈为空
                return -1;
            }
            return items[count - 1];
        }
    }

}

1.2 基于链表

由于在链表尾部进行插入和删除操作过于繁琐,所以采用头插

public class NodeStack {
    
    
    public class Node {
    
    
        public int data;
        public Node next;

        public Node(int data, Node next) {
    
    
            this.data = data;
            this.next = next;
        }
    }

    private Node head = null;

    public void push(int value) {
    
    
        Node newNode = new Node(value, null);
        newNode.next = head;
        head = newNode;
    }

    public int pop() {
    
    
        if (head == null) {
    
    
            return -1;
        }

        int value  = head.data;
        head = head.next;
        return value;
    }

    public int peek() {
    
    
        if (head == null) {
    
    
            return -1;
        }
        return head.data;
    }
}

2. 实现队列

2.1 基于数组(循环队列)

public class CQueue {
    
    
    private String[] items;
    private int n; // 队列的大小
    private int head = 0;
    private int tail = 0;

    public CQueue(int n) {
    
    
        this.items = new String[n];
        this.n = n;
    }

    public boolean enqueue(String items) {
    
    
        if ((tail + 1) % n == head) {
    
    
            return false;
        }
        tail = (tail + 1) % n;
        return true;
    }

    public String dequeue() {
    
    
        if (head == tail) {
    
    
            return null;
        }
        String result = items[head];
        head = (head + 1) % n;
        return result;
    }
}

2.2 基于链表

public class LQueue {
    
    
    private class Node {
    
    
        public String data;
        public Node next;
        public Node(String data, Node next) {
    
    
            this.data = data;
            this.next = next;
        }
        
        private Node head = null;
        private Node tail = null;
        
        public void enqueue(String value) {
    
    
            Node newNode = new Node(value, null);
            if (tail == null) {
    
    
                head = newNode;
                tail = newNode;
            } else {
    
    
                tail.next = newNode;
            }
        }
        
        public String dequeue() {
    
    
            if (head == null) {
    
    
                return null;
            }
            
            String value = head.data;
            head = head.next;
            if (head == null) {
    
    
                tail = null;
            } 
            return value;
        }
    }
}

3. 剑指 Offer 09. 用两个栈实现队列

链接:https://leetcode.cn/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof

3.1 题目

用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )

示例 1:

输入:
[“CQueue”,“appendTail”,“deleteHead”,“deleteHead”,“deleteHead”]
[[],[3],[],[],[]]
输出:[null,null,3,-1,-1]
示例 2:

输入:
[“CQueue”,“deleteHead”,“appendTail”,“appendTail”,“deleteHead”,“deleteHead”]
[[],[],[5],[2],[],[]]
输出:[null,-1,null,null,5,2]

3.2 题解

class CQueue {
    
    

    private Stack<Integer> stack = new Stack<>();
    private Stack<Integer> tmpStack = new Stack<>();

    public CQueue() {
    
    

    }
    
    public void appendTail(int value) {
    
    
        stack.push(value);
    }
    
    public int deleteHead() {
    
    

        if (stack.isEmpty()) {
    
    
            return -1;
        }

        while (!stack.isEmpty()) {
    
    
            tmpStack.push(stack.pop());
        }

        int result = tmpStack.pop();

        while (!tmpStack.isEmpty()) {
    
    
            stack.push(tmpStack.pop());
        }

        return result;

    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */

4. 用队列实现栈

链接:https://leetcode.cn/problems/implement-stack-using-queues

4.1 题目

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

注意:

你只能使用队列的基本操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。
你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。

示例:

输入:
[“MyStack”, “push”, “push”, “top”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出:
[null, null, null, 2, 2, false]

解释:
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False

4.2 题解

class MyStack {
    
    

    Queue<Integer> queue = new LinkedList<>();
    Queue<Integer> tmpQueue = new LinkedList<>();

    public MyStack() {
    
    

    }
    
    public void push(int x) {
    
    
        queue.offer(x);
        while (!tmpQueue.isEmpty()) {
    
    
            queue.offer(tmpQueue.poll());
        }
        Queue tmp = queue;
        queue = tmpQueue;
        tmpQueue = tmp;
    }
    
    public int pop() {
    
    
        return tmpQueue.poll();
    }
    
    public int top() {
    
    
        return tmpQueue.peek();
    }
    
    public boolean empty() {
    
    
        return tmpQueue.isEmpty();
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */

5. 栈排序

链接:https://leetcode.cn/problems/sort-of-stacks-lcci

5.1 题目

栈排序。 编写程序,对栈进行排序使最小元素位于栈顶。最多只能使用一个其他的临时栈存放数据,但不得将元素复制到别的数据结构(如数组)中。该栈支持如下操作:push、pop、peek 和 isEmpty。当栈为空时,peek 返回 -1。

示例1:

输入:
[“SortedStack”, “push”, “push”, “peek”, “pop”, “peek”]
[[], [1], [2], [], [], []]
输出:
[null,null,null,1,null,2]
示例2:

输入:
[“SortedStack”, “pop”, “pop”, “push”, “pop”, “isEmpty”]
[[], [], [], [1], [], []]
输出:
[null,null,null,null,null,true]
说明:

栈中的元素数目在[0, 5000]范围内。

5.2 题解

class SortedStack {
    
    

    Stack<Integer> stack = new Stack<>();
    Stack<Integer> tmpStack = new Stack<>();

    public SortedStack() {
    
    

    }
    
    public void push(int val) {
    
    
        if (stack.isEmpty()) {
    
    
            stack.push(val);
        } else {
    
    
            while (!stack.isEmpty() && val > stack.peek()) {
    
    
                tmpStack.push(stack.pop());
            }
            stack.push(val);
            while (!tmpStack.isEmpty()) {
    
    
                stack.push(tmpStack.pop());
            }
        }
        
    }
    
    public void pop() {
    
    
        if (!stack.isEmpty()) {
    
    
            stack.pop();
        } else {
    
    
            return;
        }
    }
    
    public int peek() {
    
    
        if(!stack.isEmpty()) {
    
    
            return stack.peek();
        } else {
    
    
            return -1;
        }
    }
    
    public boolean isEmpty() {
    
    
        return stack.isEmpty();
    }
}

/**
 * Your SortedStack object will be instantiated and called as such:
 * SortedStack obj = new SortedStack();
 * obj.push(val);
 * obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.isEmpty();
 */

6. 三合一

链接:https://leetcode.cn/problems/three-in-one-lcci

6.1 题目

三合一。描述如何只用一个数组来实现三个栈。

你应该实现push(stackNum, value)、pop(stackNum)、isEmpty(stackNum)、peek(stackNum)方法。stackNum表示栈下标,value表示压入的值。

构造函数会传入一个stackSize参数,代表每个栈的大小。

示例1:

输入:
[“TripleInOne”, “push”, “push”, “pop”, “pop”, “pop”, “isEmpty”]
[[1], [0, 1], [0, 2], [0], [0], [0], [0]]
输出:
[null, null, null, 1, -1, -1, true]
说明:当栈为空时pop, peek返回-1,当栈满时push不压入元素。
示例2:

输入:
[“TripleInOne”, “push”, “push”, “push”, “pop”, “pop”, “pop”, “peek”]
[[2], [0, 1], [0, 2], [0, 3], [0], [0], [0], [0]]
输出:
[null, null, null, null, 2, 1, -1, -1]

6.2 题解

class TripleInOne {
    
    

    private int[] array;
    private int n;
    private int[] top;

    public TripleInOne(int stackSize) {
    
    

        array = new int[3 * stackSize];
        n = 3 * stackSize;
        top = new int[3];
        top[0] = -3;
        top[1] = -2;
        top[2] = -1;
    }
    
    public void push(int stackNum, int value) {
    
    
        if (top[stackNum] + 3 >= n) {
    
    
            return;
        }
        top[stackNum] += 3;
        array[top[stackNum]] = value;
    }
    
    public int pop(int stackNum) {
    
    
        if (top[stackNum] < 0) {
    
    
            return -1;
        }
        int result = array[top[stackNum]];
        top[stackNum] -= 3;
        return result;
    }
    
    public int peek(int stackNum) {
    
    
        if (top[stackNum] < 0) {
    
    
            return -1;
        }
        return array[top[stackNum]];
    }
    
    public boolean isEmpty(int stackNum) {
    
    
        return top[stackNum] < 0;
    }
}

/**
 * Your TripleInOne object will be instantiated and called as such:
 * TripleInOne obj = new TripleInOne(stackSize);
 * obj.push(stackNum,value);
 * int param_2 = obj.pop(stackNum);
 * int param_3 = obj.peek(stackNum);
 * boolean param_4 = obj.isEmpty(stackNum);
 */

7. 有效的括号

链接:https://leetcode.cn/problems/valid-parentheses

7.1 题目

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = “()”
输出:true
示例 2:

输入:s = “()[]{}”
输出:true
示例 3:

输入:s = “(]”
输出:false

7.2 题解

class Solution {
    
    
    Stack<Character> stack = new Stack<>();
    public boolean isValid(String s) {
    
    

        
        for (int i = 0; i < s.length(); i++) {
    
    
            char c = s.charAt(i);
            if (compare(c)) {
    
    
                stack.push(c);
            } else {
    
    
                int result = sen(c);
                if (result == 0) {
    
    
                    return false;
                }
            }
        }

        return stack.isEmpty();

    }

    public boolean compare(char c) {
    
    
        if (c == '(' || c == '{' || c == '[') {
    
    
            return true;
        } else {
    
    
            return false;
        }
    }

    public int sen(char c) {
    
    
        if (stack.isEmpty()) {
    
    
            return 0;
        } else {
    
    
            char ch = stack.peek();
            if (c == ')' && ch == '(' || c == '}' && ch == '{' || c == ']' && ch == '[') {
    
    
                stack.pop();
                return 1;
            } else {
    
    
                return 0;
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_62759952/article/details/129148638