算法 栈与队列 day07

栈和队列

队列是先进先出,栈是先进后出。

Stack方法摘要:

  • push():把项压入堆栈顶部
  • pop():移除堆栈顶部的对象,并作为此函数的值返回该对象
  • empty():测试堆栈是否为空。
  • peek():查看堆栈顶部的对象,但不从堆栈中移除它。
  • search():返回对象在堆栈中的位置,以 1 为基数。返回值 -1 表示此对象不在堆栈中

Queue方法摘要:

  • add():将指定的元素插入此队列。成功时返回 true,如果当前没有可用的空间,则抛出异常。
  • offer():将指定的元素插入此队列。如果该元素已添加到此队列,则返回 true;否则返回 false
  • remove():获取并移除此队列的头。此方法与 poll 唯一的不同在于:此队列为空时将抛出一个异常。
  • poll():获取并移除此队列的头,如果此队列为空,则返回 null。
  • peek():获取但不移除此队列的头;如果此队列为空,则返回 null。
  • element():获取,但是不移除此队列的头。此方法与 peek 唯一的不同在于:此队列为空时将抛出一个异常。

第一题:232. 用栈实现队列 - 力扣(LeetCode)

import java.util.Stack;

public class MyQueue {
    /*用栈实现队列 leetcode_232 */

    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    /**
     * 在这里初始化您的数据结构。
     */
    public MyQueue() {
        stackIn = new Stack<>(); // 负责进栈
        stackOut = new Stack<>(); // 负责出栈
    }

    /**
     * 将元素 x 推到队列的后面。
     */
    public void push(int x) {
        stackIn.push(x);
    }

    /**
     * 从队列前面移除元素并返回该元素。
     */
    public int pop() {
        dumpstackIn();
        return stackOut.pop();
    }

    /**
     * 得到前面的元素。
     */
    public int peek() {
        dumpstackIn();
        return stackOut.peek();
    }

    /**
     * 返回队列是否为空:只要进栈和出战同时为空,则队列为空
     */
    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());
        }
    }
}

第二题:225. 用队列实现栈 - 力扣(LeetCode)

import java.util.LinkedList;
import java.util.Queue;

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

    //将队列中最后一个元素弹出,就要先将队列中最后一个元素的前面所有元素弹出再重新添加到队列中
    public void rePosition() {
        int size = queue.size();    //获取队列的大小
        size--;
        while (size-- > 0)
            queue.add(queue.poll());    //将队列中最后一个元素前面的所有元素弹出再重新添加到队列中
    }
}

第三题:20. 有效的括号 - 力扣(LeetCode)

public static boolean isValid(String s) {
        //剪枝操作
        if (s.length() % 2 != 0) {  //这个字符串的长度不为偶数,直接返回false
            return false;
        }

        //创建一个双端队列
        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. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)

//用栈操作
    public static String removeDuplicates1(String S) {
        //ArrayDeque会比LinkedList在除了删除元素这一点外会快一点
        ArrayDeque<Character> deque = new ArrayDeque<>();
        char ch;

        for (int i = 0; i < S.length(); i++) {
            ch = S.charAt(i);
            if (deque.isEmpty() || deque.peek() != ch) {
                deque.push(ch);
            } else {
                deque.pop();
            }
        }

        String str = "";
        //剩余的元素即为不重复的元素
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        return str;
    }

    //用字符串代替栈
    public static String removeDuplicates2(String s) {
        // 将 res 当做栈
        // 也可以用 StringBuilder 来修改字符串,速度更快
        StringBuffer res = new StringBuffer();

        // top为 res 的长度
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (top >= 0 && res.charAt(top) == c) { //当 top > 0, 即栈中有字符时,当前字符如果和栈中字符相等,
                res.deleteCharAt(top);  //弹出栈顶字符,同时 top--
                top--;

            } else {    //否则,将该字符入栈,同时top++
                res.append(c);
                top++;
            }
        }
        return res.toString();
    }

    //双指针
    public static String removeDuplicates3(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. 逆波兰表达式求值 - 力扣(LeetCode)

//用栈来处理
    public static int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList();

        for (String s : tokens) {
            if ("+".equals(s)) {        // leetcode 内置jdk的问题,不能使用==判断字符串是否相等
                stack.push(stack.pop() + stack.pop());      // 注意 - 和 / 需要特殊处理
            } else if ("-".equals(s)) {
                stack.push(-stack.pop() + stack.pop());
            } else if ("*".equals(s)) {
                stack.push(stack.pop() * stack.pop());
            } else if ("/".equals(s)) {
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            } else {    //将数字存入栈中,不要忘记转为int再存入
                stack.push(Integer.valueOf(s));
            }
        }
        return stack.pop();
    }

第六题:239. 滑动窗口最大值 - 力扣(LeetCode)

//暴力:不能完全通过测试用例
public static int[] maxSlidingWindow(int[] nums, int k) {
        //剪枝操作
        if (k == 1) {
            return nums;
        }

        int[] res = new int[nums.length - k + 1];
        int max = Integer.MIN_VALUE;
        int index = 0;

        for (int i = 0; i < nums.length; i++) {
            for (int j = i; j < k + i; j++) {
                // 遍历小区间中的最大值
                while (j < k + i && j < nums.length) {

                    if (nums[j] > max) {
                        max = nums[j];
                        j++;
                    } else {
                        j++;
                    }
                }
                res[index] = max;
                max = Integer.MIN_VALUE;
                index++;
                if (index == nums.length - k + 1) {
                    return res;
                }
            }
        }
        return res;
    }

第七题:347. 前 K 个高频元素 - 力扣(LeetCode)

//通过map,list来实现的
public int[] topKFrequent(int[] nums, int k) {
        // key存放元素,value存放元素出现的次数
        Map<Integer, Integer> map = new HashMap<>();

        for (int num : nums) {
            // 当集合中有这个元素时,就使这个元素的value+1,当集合中没有这个元素时,就添加0 + 1
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        // 遍历map,将value从大到小排序,放入数组中
        List<Integer> list = new ArrayList<>();

        Set<Integer> keySet = map.keySet();
        for (Integer key : keySet) {
            Integer value = map.get(key);
            list.add(value);
        }

        // 排序(从大到小)
        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });

        // System.out.println(list);//[3, 2, 1]

        // 通过value获取对应的key,只取前k个value对应的key
        int[] res = new int[k];
        for (int i = 0; i < k;) {
            Integer value = list.get(i);
            // 遍历map
            for (Integer key : keySet) {
                Integer val = map.get(key);
                if (Objects.equals(value, val)) {
                    res[i] = key;
                    i++;
                }
            }
        }
        return res;
    }
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值