栈与队列力扣题目开刷

第一题:力扣232题

解题思路:

这与栈和队列的特性有关,众所周知,栈是满足“先进后出”的,而队列是满足“先进先出”的,所以聪明的人类就想到了用两个栈来实现队列,哈哈哈,聪明!!!

代码如下:

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;
    //无参构造,初始化
    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();
    }
    //队列实现push和栈一样
    public void push(int x) {
        stackIn.push(x);
    }
    //队列弹出需要先弹出先进栈的部分,所以先判断stackOut是否为空,不为空才能将stackIn逆序全放进去,直到stackIn
    //也为空,说明全弹出来了,最后返回stackOut最上边的
    public int pop() {
        if(stackOut.isEmpty()) {
            while(!stackIn.isEmpty()) {
                stackOut.push(stackIn.pop());
            }  
        }
        return stackOut.pop();
    }
    //peek其实和pop差不多,也是得将stackOut全填满,之后out最上边的就是peek
    public int peek() {
        if(stackOut.isEmpty()) {
            while(!stackIn.isEmpty()) {
                stackOut.push(stackIn.pop());
            }  
        }
        return stackOut.peek();
    }
    //stackIn、stackOut都为空才是空
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }
}

第二题:力扣225题

基础知识参见文献一

解题思路:

思路1===》两个队列(一个存放,另一个辅助)实现栈

思路2===》一个队列(Deque)实现栈

代码如下:

//思路1:两个队列(一个存放,另一个辅助)实现栈
class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;
    //初始化
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    //压栈。将x装入队列2 ===> 将队列1中的装入队列2 ===> 将队列2全复制给队列1,以便之后使用
    public void push(int x) {
        queue2.offer(x);
        while(!queue1.isEmpty()) {
            queue2.offer(queue1.poll());
        }
        Queue<Integer> tempQueue;
        tempQueue = queue1;
        queue1 = queue2;
        queue2 = tempQueue;
    }
    //队列1的顺序即为栈中的顺序
    public int pop() {
        return queue1.poll();
    }
    //队列1的顺序即为栈中的顺序
    public int top() {
        return queue1.peek();
    }
    //队列1的顺序即为栈中的顺序
    public boolean empty() {
        return queue1.isEmpty();
    }
}
//思路2:一个队列(Deque)实现栈
class MyStack {
    Deque<Integer> deque;
    //初始化
    public MyStack() {
        deque = new ArrayDeque<>();
    }
    //压栈
    public void push(int x) {
        deque.addLast(x);
    }
    //deque除了最后一个元素其余的重新入队列,返回并删除第一个
    public int pop() {
        int size = deque.size();
        size--;
        while(size-- > 0) {
            deque.addLast(deque.pollFirst());
        }
        int res = deque.pollFirst();
        return res;
    }
    //返回deque压入的最后一个元素
    public int top() {
        return deque.peekLast();
    }
    //返回deque是否为空
    public boolean empty() {
        return deque.isEmpty();
    }

第三题:力扣20题

解题思路:

遇到这种成对出现的问题,也就是匹配的问题来说,使用栈解决非常合适!
匹配括号有三种情况:
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

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

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

代码如下:

        Stack<Character> stack = new Stack<>();
        char c;
        for(int i = 0; i < s.length(); i++) {
            c = s.charAt(i);
            if(c == '(') {
                stack.push(')');
            } else if(c == '[') {
                stack.push(']');
            } else if(c == '{') {
                stack.push('}');
            //情况三:stack.isEmpty()表示右括号没有匹配的左括号了
            //情况二:stack.peek() != c表示栈中没有匹配的字符了
            } else if(stack.isEmpty() || stack.peek() != c) {
                return false;
            } else {
                stack.pop();
            }
        }
        //情况一:字符串已遍历完,但是栈不为空,说明左括号没有匹配的右括号了
        return stack.isEmpty();

但写完这个之后,又发现别人的题解,虽然思路大同小异,但借鉴一下别人的也是一种学习,他人代码如下:

        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();

刚开始不是很理解,这就查呀查,找呀找,参照这篇文章可以一目了然,哈哈哈!!!
里边写道不论是栈stack还是队列queue,都可以用双端队列deque来实现,里边还介绍了他们的方法对比,这里就用到了deque用作栈来使用的时候,它的peek()方法与stack 的peek()方法一样了,都是从入栈的地方出栈。所以用deque.peek() != ch是没毛病的。

第四题:力扣1047题

解题思路:

同样是匹配问题,可以把字符串顺序放到一个栈中,然后如果相同的话 栈就弹出,这样最后栈里剩下的元素都是相邻不相同的元素了。

代码如下:

class Solution {
    public String removeDuplicates(String s) {
        //双端队列实现栈
        Deque<Character> deque = new ArrayDeque<>();
        char c;
        for(int i = 0; i < s.length(); i++) {
            //取出每个字符
            c = s.charAt(i);
            //栈为空或者栈顶与字符不等,压入栈;否则,弹出
            if(deque.isEmpty() || c != deque.peek()) {
                deque.push(c);
            } else {
                deque.pop();
            }
        }
        String str = "";
        //拼接成字符串
        while(!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }
}

===================================================
新的一天,继续

第五题:力扣150题

解题思路:

就凭借着逆波兰表达式的特点,参考下边这个文档
参见文档
逆波兰表达式主要有以下两个优点:

去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。

适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。

代码如下:

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList<>();
        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 down = stack.pop();
                int up = stack.pop();
                stack.push(up / down);
            } else {
                //这里需要转换成Integer
                stack.push(Integer.valueOf(tokens[i]));
            }
        }
        return stack.pop();
    }
}

第六题:力扣239题

解题思路:

自定义单调队列,完成从大到小的顺序,滑动窗口,弹出最大(最左),加入新的数,直到结束。

代码如下:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 1) {
            return nums;
        }
        //定义一个存放最大值的数组,其大小 = 数组长度 - 窗长 + 步长
        int[] arr = new int[nums.length - k + 1];
        //site记录存放位置
        int site = 0;
        //创建对象
        MyQueue queue = new MyQueue();
        //先把前k个数放入自定义队列中
        for(int i = 0; i < k; i++) {
            queue.add(nums[i]);
        }
        //存放第一个窗口中的最大值,site自加
        arr[site++] = queue.peek();
        //移动窗口,弹出一个,进来一个,把最开头的数给arr,site自加
        for(int i = k; i < nums.length; i++) {
            queue.poll(nums[i - k]);
            queue.add(nums[i]);
            arr[site++] = queue.peek();
        }
        return arr;
    }
}
//自定义一个单调队列
class MyQueue {
    Deque<Integer> deque = new LinkedList<>();

    void poll(int value) {
        //这里写成while()了,人家只要弹一次就好了,你给人家使劲弹,哈哈哈
        if(!deque.isEmpty() && value == deque.peek()) {
            deque.poll();
        }
    }

    void add(int value) {
        while(!deque.isEmpty() && value > deque.getLast()) {
            deque.removeLast();
        }
        deque.add(value);
    } 

    int peek() {
        return deque.peek();
    }
}

over!!!

你可能感兴趣的:(leetcode,leetcode,算法,职场和发展)