代码随想录算法训练营第十、十一天| 232.用栈实现队列、225.用队列实现栈、20.有效的括号、1047.删除字符串中所有相邻重复项、150.逆波兰表达式求值。

232.用栈实现队列

image-20230325115720219

image-20230325115810597

Java中栈的函数:

Stack<Integer> s = new Stack<>();
//判断栈是否为空
boolean isEmpty()
//返回栈中元素的个数
int size()
//压入元素
E push(E item)
//返回栈顶元素
E peek()
//删除并返回栈顶元素
E pop()

my solution:

class MyQueue {
    Stack<Integer> inStack;
    Stack<Integer> outStack;

    public MyQueue() {
        inStack = new Stack<>();// 负责进栈
        outStack = new Stack<>();// 负责出栈
    }
    
    //元素入栈
    public void push(int x) {
        //说明没有元素,那直接入栈即可
        if(inStack.isEmpty() && outStack.isEmpty()){
            inStack.push(x);
        //如果出栈中有元素,将其还原到入栈处
        }else if(!outStack.isEmpty()){
            while(!outStack.isEmpty()){
                inStack.push(outStack.pop());
            }
            inStack.push(x);
        }else if(!inStack.isEmpty()){
            inStack.push(x);
        }
    }
    
    //移除元素
    public int pop() {
        //不同
        if(!inStack.isEmpty()){
            while(!inStack.isEmpty()){
                outStack.push(inStack.pop());
            }
        }
        return outStack.pop();
    }
    
    public int peek() {
        //不同
        if(!inStack.isEmpty()){
            while(!inStack.isEmpty()){
                outStack.push(inStack.pop());
            }
        }
        return outStack.peek();
    }

    public boolean empty() {
        if(inStack.isEmpty() && outStack.isEmpty()){
            return true;
        }
        return false;
    }
}

有两个方向。

代码随想录:

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    /** Initialize your data structure here. */
    public MyQueue() {
        stackIn = new Stack<>(); // 负责进栈
        stackOut = new Stack<>(); // 负责出栈
    }
    
    /** Push element x to the back of queue. */
    public void push(int x) {
        stackIn.push(x);
    }
    
    /** Removes the element from in front of queue and returns that element. */
    public int pop() {    
        dumpstackIn();
        return stackOut.pop();
    }
    
    /** Get the front element. */
    public int peek() {
        dumpstackIn();
        return stackOut.peek();
    }
    
    /** Returns whether the queue is empty. */
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }

    // 如果stackOut为空,那么将stackIn中的元素全部放到stackOut中
    private void dumpstackIn(){
        if (!stackOut.isEmpty()) return; 
        while (!stackIn.isEmpty()){
            stackOut.push(stackIn.pop());
        }
    }
}

只有一个方向:将元素从入栈移动到出栈。

image-20230325152941001

225.用队列实现栈

image-20230325154629610

image-20230325164719845

注意是单向队列。

Java中队列的函数:

Queue<String> queue = new LinkedList<>();
//判断队列是否为空
boolean isEmpty()
//返回队列中元素的个数
int size()
    
//返回队头的元素
E peek()
//删除并返回队头的元素
E poll()
    
//将元素e插入队尾
boolean offer(E e)

用LinkedList来实现:

动的是入队列。

两个队列实现栈:

class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;

    public MyStack() {
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
    }
    
    //形成倒序
    public void push(int x) {
        //将x先加入到queue2中
        queue2.offer(x);
        //将queue1中的数据依次加入到queue2中
        while (!queue1.isEmpty()) {
            queue2.offer(queue1.poll());
        }
        //此时x是queue2中的第一个元素
        Queue<Integer> temp = queue1;
        queue1 = queue2;
        queue2 = temp;
    }
    
    public int pop() {
        return queue1.poll();
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.isEmpty();
    }
}

一个队列实现栈:

class MyStack {
    Queue<Integer> queue;

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

    //每 offer 一个数(A)进来,都重新排列,把这个数(A)放到队列的队首
    public void push(int x) {
        queue.offer(x);
        int size = queue.size();
        //移动除了 A 的其它数
        while (size-- > 1)
            queue.offer(queue.poll());
    }

    public int pop() {
        return queue.poll();
    }

    public int top() {
        return queue.peek();
    }

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

用Deque来实现:

动的是出队列。

public void push(int x) {
    que1.addLast(x);
}
    
public int pop() {
    int size = que1.size();
    size--;
    // 将 que1 导入 que2 ,但留下最后一个值
    while (size-- > 0) {
        que2.addLast(que1.peekFirst());
        que1.pollFirst();
    }
    int res = que1.pollFirst();
    
    // 将 que2 对象的引用赋给了 que1 ,此时 que1,que2 指向同一个队列
    que1 = que2;
    // 如果直接操作 que2,que1 也会受到影响,所以为 que2 分配一个新的空间
    que2 = new ArrayDeque<>();
    return res;
}

public int top() {
    return que1.peekLast();
}
public void push(int x) {
    que1.addLast(x);
}

public int pop() {
    int size = que1.size();
    size--;
    // 将 que1 导入 que2 ,但留下最后一个值
    while (size-- > 0) {
        que1.addLast(que1.peekFirst());
        que1.pollFirst();
    }

    int res = que1.pollFirst();
    return res;
}

public int top() {
    return que1.peekLast();
}

20.有效的括号

image-20230325171626089

用栈来实现。

image-20230325171902883

不匹配的情况:

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false

那么什么时候说明左括号和右括号全都匹配了呢,就是字符串遍历完之后,栈是空的,就说明全都匹配了。

如果是左括号,就压入对应的右括号。如果是右括号,则弹出栈顶元素与其进行匹配。

class Solution {
    public boolean isValid(String s) {
        if(s.length()%2 != 0){
            return false;
        }
        Stack<Character> stack = new Stack<>();
        for(int i=0;i<s.length();i++){
            if(s.charAt(i) == '('){
                stack.push(')');
            }else if(s.charAt(i) == '['){
                stack.push(']');
            }else if(s.charAt(i) == '{'){
                stack.push('}');
            }else if(stack.isEmpty() || s.charAt(i)!=stack.peek()){
                return false;
            }else{//右括号与栈顶元素匹配
                stack.pop();
            }
        }
        return stack.isEmpty();//如果最后栈为空,则为true
    }
}

image-20230327110856931

LinkedList也是Deque的一种实现。

class Solution {
    public boolean isValid(String s) {
        Deque<Character> deque = new LinkedList<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            //碰到左括号,就把相应的右括号入栈
            if (ch == '(') {
                deque.push(')');
            }else if (ch == '{') {
                deque.push('}');
            }else if (ch == '[') {
                deque.push(']');
            } else if (deque.isEmpty() || deque.peek() != ch) {
                return false;
            }else {//如果是右括号判断是否和栈顶元素匹配
                deque.pop();
            }
        }
        //最后判断栈中元素是否匹配
        return deque.isEmpty();
    }
}

1047.删除字符串中所有相邻重复项

image-20230327111247559

class Solution {
    public String removeDuplicates(String s) {
        //双端队列
        Deque<Character> deque = new LinkedList<>();
        for(int i=0;i<s.length();i++){
            if(deque.isEmpty()){
                deque.addLast(s.charAt(i));
                continue;
            }
            //只能碰掉一个,所以用if,而不是while
            if(!deque.isEmpty() && deque.peekLast() == s.charAt(i)){
                deque.pollLast();
            }else{
                deque.addLast(s.charAt(i));
            }
        }
        StringBuilder sb = new StringBuilder();
        while(!deque.isEmpty()){
            sb.append(deque.pollFirst());
        }
        return new String(sb);
    }
}
class Solution {
    public String removeDuplicates(String s) {
        // 将 res 当做栈
        // 也可以用 StringBuilder 来修改字符串,速度更快
        // StringBuilder res = new StringBuilder();
        StringBuffer res = new StringBuffer();
        // top为 res 的长度
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            // 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
            if (top >= 0 && res.charAt(top) == c) {
                res.deleteCharAt(top);
                top--;
            // 否则,将该字符 入栈,同时top++
            } else {
                res.append(c);
                top++;
            }
        }
        return res.toString();
    }
}

双指针:

class Solution {
    public String removeDuplicates(String s) {
        char[] ch = s.toCharArray();
        int fast = 0;
        int slow = 0;
        while(fast < s.length()){
            // 直接用fast指针覆盖slow指针的值
            ch[slow] = ch[fast];
            // 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了
            if(slow > 0 && ch[slow] == ch[slow - 1]){
                slow--;
            }else{
                slow++;
            }
            fast++;
        }
        return new String(ch,0,slow);
    }
}

150.逆波兰表达式求值

image-20230327150011224

image-20230327150133688

与5差不多,只不过本题不是相邻元素做消除了,而是做运算。

先弹出来的是右操作数。

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        //先弹出来的是右操作数
        for(int i=0;i<tokens.length;i++){
            if ("+".equals(tokens[i])) {
                stack.push(stack.pop() + stack.pop()); 
            } else if ("-".equals(tokens[i])) {
                stack.push(-stack.pop() + stack.pop());
            } else if ("*".equals(tokens[i])) {
                stack.push(stack.pop() * stack.pop());
            } else if ("/".equals(tokens[i])) {
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            } else {
                stack.push(Integer.valueOf(tokens[i]));
            }
        }
        return stack.pop();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值