后进先出
//利用双端队列实现
Deque<> stack = new LinkedList<>();
//双端队列实现栈的常用方法
stack.push()
stack.pop()
stack.peek()
stack.isEmpty()
先进先出
Queue<> que = new LinkedList<>();
//个人习惯采用第一种
//成功返回true,失败时返回一个特殊值(取决于操作,为NULL或false)
que.offer();
que.poll();
que.peek();
//成功返回true,在操作失败时抛出异常
add(E e):添加一个元素到队尾
remove():获取队首的元素,并从队列中移除
element():获取队首的元素,但不从队列中移除
//
que.isEmpty();
对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆),
从队头到队尾按从大到小排就是最大堆(大顶堆)—>队头元素相当于堆的根节点
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。
单调栈刷题总结
class Solution {
//优先队列实现大顶堆
//getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
public int[] topKFrequent(int[] nums, int k) {
//1.计算值与出现频率
Map<Integer,Integer> map = new HashMap<>();
for(int i=0;i<nums.length;i++){
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
}
//2.创建大顶堆(从大到小),然后把map的值放到里面
//大顶堆 [ [key,count], ... ]
PriorityQueue<int[]> pq = new PriorityQueue<>( (x,y) -> y[1]-x[1]);
//用map.entrySet 把map解析为 entry类型
for(Map.Entry<Integer,Integer> entry:map.entrySet()){
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
//3.存放结果
int[] res = new int[k];
for(int i = 0;i<k;i++){
res[i] = pq.poll()[0];
}
return res;
}
}
class Solution {
//小顶堆
public int[] smallestK(int[] arr, int k) {
PriorityQueue<Integer> pq = new PriorityQueue<Integer>((x,y)->(x-y));//小顶堆
for(int i=0;i<arr.length;i++){
pq.offer(arr[i]);//队头到队尾:从小到大
}
int[] res = new int[k];
for(int i=0;i<k;i++){
res[i] = pq.poll();
}
return res;
}
}
class MyQueue {
Deque<Integer> stackIn;
Deque<Integer> stackOut;
public MyQueue() {
stackIn = new LinkedList<Integer>();
stackOut = new LinkedList<Integer>();
}
public void push(int x) {
stackIn.push(x);
}
public int pop() {
contrustOut();
return stackOut.pop();
}
public int peek() {
contrustOut();
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty() && stackOut.isEmpty();
}
public void contrustOut(){
if(!stackOut.isEmpty()) return;
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
class MyStack {
//queue内置方法
//offer添加元素
//poll返回第一个元素,并删除
//peek返回第一个元素
//核心做法:构造满足栈要求的队列,利用一个辅助队列来对元素排序后,放到目标队列里面去
//画图分析思路较为清晰
Queue<Integer> que1;//用来模拟栈
Queue<Integer> que2;//辅助队列
public MyStack() {
que1 = new LinkedList<>();
que2 = new LinkedList<>();
}
public void push(int x) {
que2.offer(x);
while (!que1.isEmpty()){
que2.offer(que1.poll());//新的队列,符合栈要求的队列
}
Queue<Integer> tempQue = que1;
que1 = que2;//队列1为最终结果
que2 = tempQue;//队列2为空队列
}
public int pop() {
return que1.poll();
}
public int top() {
return que1.peek();
}
public boolean empty() {
return que1.isEmpty();
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new LinkedList<>();
if(s.length()==1) return false;
for(int i=0;i<s.length();i++){
char ch = s.charAt(i);
if(ch == ')'){
if(stack.isEmpty() || stack.pop()!='(') return false;
}
else if(ch == ']'){
if(stack.isEmpty() || stack.pop()!='[') return false;
}
else if(ch == '}'){
if(stack.isEmpty() || stack.pop()!='{') return false;
}else{
stack.push(ch);
}
}
return stack.isEmpty();
}
}
class Solution {
public String removeDuplicates(String s) {
Deque<Character> stack = new LinkedList<Character>();
stack.push(s.charAt(0));
for(int i=1;i<s.length();i++){
if(stack.isEmpty() || s.charAt(i) != stack.peek()){
stack.push(s.charAt(i));
}else{
stack.pop();
}
}
String str = "";
while(!stack.isEmpty()){
str = stack.pop() + str;
}
return str;
}
}
class Solution {
//遇到数字就入栈
//遇到符号就弹出两个数字 进行处理后压入栈
//Integer.valueOf 将基本类型int转换为包装类型Integer,或者将String转换成Integer
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<Integer>();
for(int i = 0;i<tokens.length;i++){
String s = tokens[i];
if( s.equals("+") ){// leetcode 内置jdk的问题,不能使用==判断字符串是否相等
stack.push(stack.pop() + stack.pop());
}else if(s.equals("-")){
stack.push(-stack.pop()+stack.pop());
}else if (s.equals("*")){
stack.push(stack.pop()*stack.pop());
}else if (s.equals("/")){
int temp1 = stack.pop();
int temp2 = stack.pop();
stack.push(temp2/temp1);
}else{
stack.push(Integer.valueOf(s));
}
}
return stack.pop();
}
}
class Solution {
//只有 加减括号
//加减可以单独算,就用一个sign可以完成
//遇到括号才入栈,依次是数字、符号
//右括号就出栈,算出最终结果
public int calculate(String s) {
Deque<Integer> stack = new LinkedList<>();
int sign = 1;//1代表正号 -1代表负号
int len = s.length();
int num = 0;
for(int i=0;i<len;i++){
char c = s.charAt(i);
if(Character.isDigit(c)){
int cur = c - '0';
while(i+1<len && Character.isDigit(s.charAt(i+1))){
cur = cur * 10 + s.charAt(i+1) - '0';
i++;
}
num = num + sign * cur;//只要没遇到符号和括号 就把结果算出来
}else if(c == '+'){
sign = 1;
}else if(c == '-'){
sign = -1;
}else if(c == '('){
stack.push(num);
num = 0;
stack.push(sign);
sign = 1;//先放数字后放符号
}else if(c == ')'){
num = stack.pop() * num + stack.pop();
}
}
return num;
}
}