算法Day9|栈基础;232-栈实现队列;225-队列实现栈;20-有效的括号;1047-删除相邻重复项

47 阅读3分钟

1、栈与队列理论基础

栈和队列的原理大家应该很熟悉,队列是先进先出,栈是先进后出。对于队列和栈,它们的操作是受限的,队列只能在一端插入元素,另一端删除元素;栈只能从某一端插入和删除元素。

这两种数据结构的API如下:

// 队列的基本 API
class MyQueue<E> {
    // 向队尾插入元素,时间复杂度 O(1)
    void push(E e);

    // 从队头删除元素,时间复杂度 O(1)
    E pop();

    // 查看队头元素,时间复杂度 O(1)
    E peek();

    // 返回队列中的元素个数,时间复杂度 O(1)
    int size();
}
// 栈的基本 API
class MyStack<E> {
    // 向栈顶插入元素,时间复杂度 O(1)
    void push(E e);

    // 从栈顶删除元素,时间复杂度 O(1)
    E pop();

    // 查看栈顶元素,时间复杂度 O(1)
    E peek();

    // 返回栈中的元素个数,时间复杂度 O(1)
    int size();
}

2、题目1:232-用栈实现队列

链接:leetcode.cn/problems/im…

类型:简单

思路:在 push 数据的时候,只要数据放进输入栈就好,但在 pop 的时候,操作就复杂一些,输出栈如果为空,就把入栈的数据猼导入进来,再从输出栈弹出数据,如果输出栈不为空,则直接从输出栈弹出数据。

如果进栈和出栈都为空的话,说明模拟的队列为空。

public class MyQueue {

    Stack<Integer> stackIn;
    Stack<Integer> stackOut;
    public MyQueue(){
        stackIn =new Stack<>();
        stackOut = new Stack<>();
    }

    public void push(int x){
        stackIn.push(x);
    }

    // 操作复杂,输出栈如果为空,就把进栈数据全部导入进来,再从栈弹出数据,
public int pop(){
       if(stackOut.isEmpty()){
           while (!stackIn.isEmpty()){
               stackOut.push(stackIn.pop());
           }
       }
       return stackOut.pop();
    }

    public int peek(){
        if(stackOut.isEmpty()){
            while (!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());
            }
        }
        return stackOut.peek();
    }

    public boolean empty(){
        return stackIn.isEmpty() && stackOut.isEmpty();
    }
}

3、题目2:225-用队列实现栈

题目:leetcode.cn/problems/im…

类型:简单

思路:一个队列在模拟栈弹出元素的时候,只要将队列头部的元素(除了最后一个元素外)重新添加到队列尾部,此时再取弹出元素就算栈的顺序了。

public class MyStack {
    Queue<Integer> queue;

    public MyStack(){
        queue = new LinkedList<>();
    }

    // 入栈
public void push(int x){
        queue.add(x);
    }

    // 移除栈顶元素
public int pop(){
        rePosition();
        return queue.poll();
    }

    public int top(){
        rePosition();
        int result = queue.poll();
        queue.add(result);
        return result;
    }

    public boolean empty(){
        return queue.isEmpty();
    }

    private void rePosition() {
        int size = queue.size();
        size--;
        while (size > 0){
            queue.add(queue.poll()); // 队列首部元素移动到末尾
size--;
        }
    }
}

4、题目3:20-有效的括号

题目:leetcode.cn/problems/va…

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

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。
public static boolean isValid(String s) {
    HashMap<Character, Character> map = new HashMap<>();
    map.put('{','}');
    map.put('(',')');
    map.put('[',']');

    Stack<Character> stack = new Stack<>();
    for (char c : s.toCharArray()) {
        if(map.containsKey(c)){
            stack.add(c);
        }else{
            if(stack.isEmpty() || !map.get(stack.pop()).equals(c)){
                return false;
            }
        }
    }
    //剩余的单个元素没找到对象
if(stack.size()>0){
        return false;
    }
    return true;
}

5、题目4:1047-删除字符串中的所有相邻重复项

题目:leetcode.cn/problems/re…

类型:简单

示例:

输入: "abbaca" 输出: "ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。

思路很简单,就是栈实现,每放入一个元素,就从栈中取出元素判断是否相等,如果相等就出栈,直到没有重复的元素。

public static String removeDuplicates(String s) {
    Stack<Character> stack = new Stack<>();

    for (char c : s.toCharArray()) {
        judgeStackDuplicat(c, stack);
    }
    StringBuffer buffer = new StringBuffer();

    for (Character c : stack) {
        buffer.append(c);
    }
    return buffer.toString();
}

private static void judgeStackDuplicat(Character s, Stack<Character> stack) {
    boolean falg = true;
    while (stack.size()>0){
        Character peek = stack.peek();
        if(peek.equals(s)){
            stack.pop();
            falg = false;
        }else{
            break;
        }
    }
    // 没有发生了移除元素的操作,那就可以放入这个元素
if(falg){
        stack.add(s);
    }
}