代码随想录算法训练营第十天 | 232.用栈实现队列 | 20. 有效的括号 | 1047. 删除字符串中的所有相邻重复项

Day 10 总结

  • 自己实现中遇到哪些困难
    • 失误还是很多,没有考虑完全一些特殊情况和边界情况
  • 今日收获,记录一下自己的学习时间
    • 16:30 - 18:00
  • 解惑(补充)

理论基础

  • 栈和队列属于容器,内部使用其他数据结构实现,提供特定操作
  • 栈:先进后出
  • 队列:先进先出
  • Java 栈
    • Stack<Integer> stack = new Stack<>();
      push
      pop
      peek
      isEmpty
  • Java 队列
    • 普通队列 (LinkedList)
    • Queue<Integer> queue = new LinkedList<>();
      offer / add
      poll
      peek
      isEmpty
    • 优先级队列 (PriorityQueue)
    • // 默认小顶堆
      PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
      // 创建大顶堆
      PriorityQueue<Integer> priorityQueue = 
      			new PriorityQueue<>(Comparator.reverseOrder());
      // 定义元素
      Comparator<Map.Entry<Integer, Integer>> myComparator = new Comparator<>() 
      {
          @Override
          public int compare(
                  Map.Entry<Integer,Integer> e1,
                  Map.Entry<Integer,Integer> e2) 
          {
              return e1.getValue() - e2.getValue();
              // return Integer.compare(int1, int2);
          }
      };
      
      PriorityQueue<Map.Entry<Integer, Integer>> pq = new PriorityQueue<>(myComparator);
      
      
      // Lambda表达式写法
      Comparator<Task> priorityComparator = 
      	(task1, task2) -> task2.priority - task1.priority;
    • 双端队列 (ArrayDeque)
    • // ArrayDeque可以作为栈和双端队列使用
      Deque<Integer> stack = new ArrayDeque<>();
      Deque<Integer> deque = new ArrayDeque<>();
      Deque<Integer> deque = new LinkedListL<>();
      addFirst
      addLast
      removeFirst
      peekFirst()
    • Map 与 优先级队列
    • // Map
      Map<Integer, Integer> map = new HashMap<>();
      Map.Entry<Integer, Integer>
      map.entrySet()
      map.containsKey()
      map.keySet()
      map.values()
      
      // Comparator
      Comparator<Map.Entry<Integer, Integer>> myComparator 
          = new Comparator<>() 
      {
      	@Override
      	public int compare(Map.Entry<Integer,Integer> e1,
      					   Map.Entry<Integer,Integer> e2) {
      		return e1.getValue() - e2.getValue();
      	}
      };
      
      // PQ	
      PriorityQueue<Map.Entry<Integer, Integer>> pq 
          = new PriorityQueue<>(myComparator);
      pq.poll()
      pq.add()

  • 栈与队列的内部实现机制

文章讲解:代码随想录

232.用栈实现队列 (简单)

题目链接/文章讲解/视频讲解:代码随想录

题目链接:https://leetcode.cn/problems/implement-queue-using-stacks/description/

实现思路:

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(pushpoppeekempty):

实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

两个栈实现队列:当元素压入队列当中时,把输出栈元素倒入输入栈,再把元素压入输入栈中;当需要抛出元素时,把输入栈中的元素倒入到输出栈中,再从输出栈中抛出元素;

代码实现:

class MyQueue {
    Stack<Integer> in;
    Stack<Integer> out;

    public MyQueue() {
        in = new Stack<>();
        out = new Stack<>();
    }
    
    public void push(int x) {
        while (!out.isEmpty()) in.push(out.pop()); // 该步骤可省略
        in.push(x);
    }
    
    public int pop() {
        while (!in.isEmpty()) out.push(in.pop());
        return out.pop();
    }
    
    public int peek() {
        while (!in.isEmpty()) out.push(in.pop());
        return out.peek();
    }
    
    public boolean empty() {
        return in.isEmpty() && out.isEmpty();
    }
}

225. 用队列实现栈 (简单)

建议大家掌握一个队列的方法,更简单一些,可以先看视频讲解

题目链接/文章讲解/视频讲解:代码随想录

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

实现思路:

使用一个队列实现栈:压入元素的时候按序压入,抛出元素的时候,遍历整个队列,找到最后一个压入的元素,抛出。遍历过程中再将元素重新压入到队列尾部。可以通过size变量进行计数,也可以通过比较目前队列头部元素否为最开始时的队首元素,判断是否抛出的是最后一个元素。

我的失误:

实现 pop 的时候没有考虑特殊情况当队列内只有一个元素时,即队首元素就是队尾元素。

代码实现:

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

public int pop() {
    Integer first = queue.poll();
    if (queue.isEmpty()) return first;

    Integer result = first;
    while (queue.peek() != first) {
        queue.add(result);
        result = queue.poll();
    }
    return result;
}

// 通过size变量实现计数
public int pop() {
    int size = queue.size();
    while (size-- > 1) 
        queue.add(queue.poll());
    return queue.poll();
}

public int top() {
    Integer result = pop();
    queue.add(result);
    return result;
}

卡哥的思路是压入的时候就进行排序,把刚压入的元素直接放在队首,方便抛出操作。

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

20. 有效的括号 (简单)

题目链接/文章讲解/视频讲解:代码随想录

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

实现思路:

括号一定是成对出现,出现右边括号的时候一定能消除掉一个左括号,如果出现了左括号不匹配右括号的情况,说明出现不成对的括号。通过栈结构存储左括号,匹配出现的右括号进行消除。

我的失误:

忽略了栈空时不能 peek,忽略了如果结束了之后栈不为空说明还有未匹配的括号。

代码实现:

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

    char[] arr = s.toCharArray();
    for (int i=0; i<arr.length; i++) {
        if (arr[i] == '{' || arr[i] == '(' || arr[i] == '[')
            stack.push(arr[i]);
        else {
            if (stack.isEmpty()) return false;
            if (arr[i] == '}') {
                if (stack.peek() == '{') stack.pop();
                else return false;
            }
            else if (arr[i] == ')') {
                if (stack.peek() == '(') stack.pop();
                else return false;
            }
            else if (arr[i] == ']') {
                if (stack.peek() == '[') stack.pop();
                else return false;
            }
        }
    }
    return stack.isEmpty();
}

1047. 删除字符串中的所有相邻重复项 (简单)

题目链接/文章讲解/视频讲解:代码随想录

题目链接:https://leetcode.cn/problems/remove-all-adjacent-duplicates-in-string/

实现思路:

给出由小写字母组成的字符串 s重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 s 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

同上题一样,匹配左右括号变成匹配相同字符。再把栈中字符组成字符串。

代码实现:

public String removeDuplicates(String s) {
    Stack<Character> stack = new Stack<>();
    char[] arr = s.toCharArray();
    for (int i=0; i<arr.length; i++) {
        char c = arr[i];
        if (!stack.isEmpty() && c == stack.peek()) 
            stack.pop();
        else stack.push(c);
    }
    arr = new char[stack.size()];
    for (int i=stack.size()-1; i>=0; i--) 
        arr[i] = stack.pop();
    return new String(arr);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值