方法总结
辅助栈、大顶堆
JZ9 用两个栈实现队列
用两个栈来实现一个队列,使用n个元素来完成 n 次在队列尾部插入整数(push)和n次在队列头部删除整数(pop)的功能。 队列中的元素为int类型。保证操作合法,即保证pop操作时队列内已有元素。数据范围: n≤1000
要求:存储n个元素的空间复杂度为 O(n) ,插入与删除的时间复杂度都是 O(1)
例:
输入:[“PSH1”,“PSH2”,“POP”,“POP”]
返回值:1,2
说明:
"PSH1":代表将1插入队列尾部 "PSH2":代表将2插入队列尾部 "POP“:代表删除一个元素,先进先出=>返回1 "POP“:代表删除一个元素,先进先出=>返回2
import java.util.*;
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
while(!stack1.isEmpty()){
stack2.push(stack1.pop());
}
int res = stack2.pop();
while(!stack2.isEmpty()){
stack1.push(stack2.pop());
}
return res;
}
}
JZ30 包含min函数的栈
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的 min 函数,输入操作时保证 pop、top 和 min 函数操作时,栈中一定有元素。
要求:时间复杂度都是 O(1)
例:
输入: [“PSH-1”,“PSH2”,“MIN”,“TOP”,“POP”,“PSH1”,“TOP”,“MIN”]
返回值:-1,2,1,-1
import java.util.*;
import java.util.Stack;
1、辅助栈
public class Solution {
Stack<Integer> stack1 = new Stack<>();
Stack<Integer> stack2 = new Stack<>();
public void push(int node) {
stack1.push(node);
if(stack2.isEmpty() || stack2.peek() > node){
stack2.push(node);
}else{
stack2.push(stack2.peek());
}
}
public void pop() {
stack1.pop();
stack2.pop();
}
public int top() {
return stack1.peek();
}
public int min() {
return stack2.peek();
}
}
2、一个栈
import java.util.*;
import java.util.Stack;
public class Solution {
Stack<Integer> stack = new Stack<>();
int min = Integer.MAX_VALUE;
public void push(int node) {
stack.push(min);
min = Math.min(node, min);
stack.push(node);
}
public void pop() {
stack.pop();
min = stack.pop();
}
public int top() {
return stack.peek();
}
public int min() {
return min;
}
}
3、记录差值
class MinStack {
Stack<Integer> stack;
int min;
/** initialize your data structure here. */
public MinStack() {
stack=new Stack<>();
}
public void push(int x) {
if (stack.isEmpty()){
min=x;
stack.push(0);
}else {
int a = x-min;
stack.add(a);
min=a<0?x:min;
}
}
public void pop() {
int b = stack.pop();
if (b<0){
min=min-b;
}
}
public int top() {
if (stack.peek()>0){
return stack.peek()+min;
}else {
return min;
}
}
public int min() {
return min;
}
}
JZ31 栈的压入、弹出序列
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。
例:
输入:[1,2,3,4,5],[4,5,3,2,1]
返回值:true
import java.util.*;
public class Solution {
public boolean IsPopOrder (int[] pushV, int[] popV) {
// write code here
if(pushV.length == 0 || popV.length == 0 || pushV.length != popV.length){
return false;
}
int len = pushV.length;
Stack<Integer> s = new Stack<>();
int j = 0;
for(int i=0; i<len; ++i){
while(j<len && (s.isEmpty() || s.peek() != popV[i])){
s.push(pushV[j]);
j++;
}
if(s.peek() == popV[i]){
s.pop();
}else{
return false;
}
}
return true;
}
}
JZ73 翻转单词序列
例
输入:“nowcoder. a am I”
输出:“I am a nowcoder.”
import java.util.*;
public class Solution {
public String ReverseSentence(String str) {
Stack<String> st = new Stack<>();
String[] arr = str.split(" ");
for(String item : arr){
st.push(item);
st.push(" ");
}
if(!st.isEmpty()){
st.pop();
}
StringBuilder res = new StringBuilder();
while(!st.isEmpty()){
res.append(st.pop());
}
return res.toString();
}
}
JZ59 滑动窗口的最大值
给定一个长度为 n 的数组 num 和滑动窗口的大小 size ,找出所有滑动窗口里数值的最大值。
例
输入:[2,3,4,2,6,2,5,1],3
输出:[4,4,6,6,6,5]
1、暴力
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows (int[] num, int size) {
ArrayList<Integer> res = new ArrayList<>();
if(size == 0 || size >num.length){
return res;
}
for(int i=0; i <=num.length-size; i++){
int max = num[i];
for(int j=i+1; j<i+size; j++){
max = Math.max(max, num[j]);
}
res.add(max);
}
return res;
}
}
2、大顶堆
import java.util.*;
//思路:用一个大顶堆,保存当前滑动窗口中的数据。滑动窗口每次移动一格,就将前面一个数出堆,后面一个数入堆。
public class Solution {
public PriorityQueue<Integer> maxQueue = new PriorityQueue<Integer>((o1,o2)->o2-o1);//大顶堆
public ArrayList<Integer> result = new ArrayList<Integer>();//保存结果
public ArrayList<Integer> maxInWindows(int [] num, int size)
{
if(num==null || num.length<=0 || size<=0 || size>num.length){
return result;
}
int count=0;
for(;count<size;count++){//初始化滑动窗口
maxQueue.offer(num[count]);
}
while(count<num.length){//对每次操作,找到最大值(用优先队列的大顶堆),然后向后滑动(出堆一个,入堆一个)
result.add(maxQueue.peek());
maxQueue.remove(num[count-size]);
maxQueue.add(num[count]);
count++;
}
result.add(maxQueue.peek());//最后一次入堆后没保存结果,这里额外做一次即可
return result;
}
}