目录
232. 用栈实现队列
225. 用队列实现栈
20. 有效的括号
1047. 删除字符串中的所有相邻重复项
150. 逆波兰表达式求值
239. 滑动窗口最大值
347. 前 K 个高频元素
刷题顺序及思路来源于代码随想录,网站地址:https://programmercarl.com
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push
、pop
、peek
、empty
):
实现 MyQueue
类:
void push(int x)
将元素 x 推到队列的末尾int pop()
从队列的开头移除并返回元素int peek()
返回队列开头的元素boolean empty()
如果队列为空,返回 true
;否则,返回 false
说明:
push to top
, peek/pop from top
, size
, 和 is empty
操作是合法的。MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false
import java.util.ArrayDeque;
import java.util.Deque;
/**
* @author light
* @Description 用栈实现队列
*
* 定义两个栈,一个输入栈,一个输出栈
* 入栈操作:将所有元素加入发到输入栈中
* 出栈操作:要实现队列的先进先出,首先先判断输出栈中是否为空,如果为空,则将输入栈
* 中的元素全部加入输出栈中,从输出栈中将元素弹出,以实现队列先进先出的功能
* @create 2023-08-11 16:56
*/
public class MyQueueTest {
public static void main(String[] args) {
MyQueue obj = new MyQueue();
obj.push(1);
obj.push(2);
int param_3 = obj.peek();
System.out.println(param_3);
int param_2 = obj.pop();
System.out.println(param_2);
boolean param_4 = obj.empty();
System.out.println(param_4);
}
}
class MyQueue {
Deque stackIn;
Deque stackOut;
public MyQueue() {
stackIn=new ArrayDeque<>();
stackOut=new ArrayDeque<>();
}
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();
}
public void dumpstackIn(){
if(stackOut.isEmpty()){
//如果输出栈中为空,将输入栈中所有元素加入到输出栈中
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
}
}
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push
、top
、pop
和 empty
)。
实现 MyStack
类:
void push(int x)
将元素 x 压入栈顶。int pop()
移除并返回栈顶元素。int top()
返回栈顶元素。boolean empty()
如果栈是空的,返回 true
;否则,返回 false
。注意:
push to back
、peek/pop from front
、size
和 is empty
这些操作。MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
myStack.top(); // 返回 2
myStack.pop(); // 返回 2
myStack.empty(); // 返回 False
package com.light.code.leetcode.stack_queue;
import java.util.Deque;
import java.util.LinkedList;
/**
* @author light
* @Description 用队列实现栈
*
*利用两个队列版
另一种方法:直接使用ArrayDeque双端队列进行实现
*
* @create 2023-08-11 17:28
*/
public class MyStackTest {
public static void main(String[] args) {
MyStack myStack = new MyStack();
myStack.push(1);
myStack.push(2);
System.out.println(myStack.top()); // 返回 2
System.out.println(myStack.pop()); // 返回 2
System.out.println(myStack.empty()); // 返回 False
}
}
class MyStack {
Deque que1;
Deque que2;
public MyStack() {
que1=new LinkedList<>();
que2=new LinkedList<>();
}
public void push(int x) {
que1.add(x);
}
public int pop() {
while(que1.size()!=1){
que2.add(que1.pop());
}
int res=que1.pop();
while(!que2.isEmpty()){
que1.add(que2.pop());
}
return res;
}
public int top() {
return que1.peekLast();
}
public boolean empty() {
return que1.isEmpty();
}
}
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
输入:s = "()"
输出:true
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
/**
* @author light
* @Description 有效的括号
*
* 采用栈解决
* @create 2023-08-11 18:14
*/
public class IsValidTest {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String s=input.next();
boolean res = isValid(s);
System.out.println(res);
}
public static boolean isValid(String s) {
Deque stack=new ArrayDeque<>();
for (int i = 0; i < s.length(); i++) {
char ch=s.charAt(i);
if(ch=='('){
stack.push(')');
} else if (ch=='{') {
stack.push('}');
}else if (ch=='[') {
stack.push(']');
} else if (stack.isEmpty()||ch!=stack.peek()) {
return false;
}else {
stack.pop();
}
}
return stack.isEmpty();
}
}
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
输入:"abbaca"
输出:"ca"
解释:
例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
/**
* @author light
* @Description 删除字符串中的所有相邻重复项
* @create 2023-08-11 18:39
*/
public class RemoveDuplicatesTest {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String s=input.next();
s=removeDuplicates(s);
System.out.println(s);
}
public static String removeDuplicates(String s) {
Deque que=new ArrayDeque<>();
que.push(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
char ch=s.charAt(i);
if(!que.isEmpty()&&ch==que.peek()){
que.pop();
}else {
que.push(ch);
}
}
String s1="";
while(!que.isEmpty()){
s1=que.pop()+s1;
}
return s1;
}
}
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
'+'
、'-'
、'*'
和 '/'
。输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Scanner;
/**
* @author light
* @Description 逆波兰表达式求值
*
* (利用栈
* @create 2023-08-12 13:36
*/
public class EvalRPNTest {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
String[] tokens=input.next().split(",");
int res=evalRPN(tokens);
System.out.println(res);
}
public static int evalRPN(String[] tokens) {
Deque stack=new ArrayDeque<>();
for (String s:tokens){
if ("+".equals(s)) {
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 {
stack.push(Integer.parseInt(s));
}
}
return stack.peek();
}
}
给你一个整数数组 nums
,有一个大小为 k
的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k
个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值
--------------- -----
[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7
package com.light.code.leetcode.stack_queue;
import java.util.Arrays;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Scanner;
/**
* @author light
* @Description 滑动窗口最大值
*
* 自定义队列:队列口中始终存放滑动窗口中的最大值;队内元素单调递减
* @create 2023-08-12 14:18
*/
public class MaxSlidingWindowTest {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt();
int[] nums=new int[n];
for (int i = 0; i < n; i++) {
nums[i]=input.nextInt();
}
int k=input.nextInt();
int[] res=maxSlidingWindow(nums,k);
System.out.println(Arrays.toString(res));
}
public static int[] maxSlidingWindow(int[] nums, int k) {
MyQue que=new MyQue();
int[] res=new int[nums.length-k+1]; //定义结果数组
int index=0;
for (int i = 0; i < k; i++) {
que.add(nums[i]);
}
res[index++]=que.getMaxValue();
for (int i = k; i < nums.length; i++) {
//维持滑动窗口,保证队列头部元素是该滑动窗口的最大值
que.pop(nums[i-k]);
que.add(nums[i]);
res[index++]=que.getMaxValue();
}
return res;
}
}
//自定义队列
class MyQue{
Deque que=new LinkedList<>();
//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
//保证队列元素单调递减
//比如此时队列元素3,1;2将要入队,2比1大,所以1弹出,此时队列:3,2
public void add(int x){
while(!que.isEmpty()&&que.getLast()
给你一个整数数组 nums
和一个整数 k
,请你返回其中出现频率前 k
高的元素。你可以按 任意顺序 返回答案。
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
import java.util.*;
/**
* @author light
* @Description 前k个高频元素
*
*(利用小顶堆,堆中只维护k个元素
* @create 2023-08-12 15:55
*/
public class TopKFrequentTest {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int n=input.nextInt();
int[] nums=new int[n];
for (int i = 0; i < n; i++) {
nums[i]=input.nextInt();
}
int k=input.nextInt();
int[] res=topKFrequent(nums,k);
System.out.println(Arrays.toString(res));
}
public static int[] topKFrequent(int[] nums, int k) {
Map map=new HashMap<>();
//key:元素;value:元素所出现的频率
for (int i = 0; i < nums.length; i++) {
map.put(nums[i],map.getOrDefault(nums[i],0)+1);
}
//按小顶堆排序(从小到大排
PriorityQueue que=new PriorityQueue<>(k, new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
return map.get(o1)-map.get(o2);
}
});
for (Integer key:map.keySet()){
if(que.size()map.get(que.peek())){
que.poll();
que.add(key);
}
}
int[] res=new int[k];
for (int i = 0; i < res.length; i++) {
res[i]=que.poll();
}
return res;
}
}