1.栈的基本知识
2.例题
1.返回栈最小元素
import java.util.Stack;
//可查询最小值的栈设计
public class Solution {
Stack<Integer> stackData=new Stack<Integer>();//保存元素
Stack<Integer> stackMin=new Stack<Integer>();//保存从stackData的栈中元素的最小值集合
public void push(int node) {
stackData.push(node);
if(stackMin.isEmpty()||node<stackMin.peek()){
stackMin.push(node);
}else{
stackMin.push(stackMin.peek());
}
}
public void pop() {
stackData.pop();
stackMin.pop();
}
public int top() {
return stackData.peek();
}
public int min() {
return stackMin.peek();
}
}
2.双栈队列
编写一个类,只能用两个栈结构实现队列,支持队列的基本操作(push,pop)。
给定一个操作序列ope及它的长度n,其中元素为正数代表push操作,为0代表pop操作,保证操作序列合法且一定含pop操作,请返回pop的结果序列。
测试样例:
[1,2,3,0,4,0],6
返回:[1,2]
import java.util.*;
//双栈队列练习题
public class TwoStack {
Stack<Integer> stackPush=new Stack<Integer>();
Stack<Integer> stackPop=new Stack<Integer>();
public int[] twoStack(int[] ope, int n) {
int index=0;
for(int i=0;i<n;i++){
int cur=ope[i];
if(cur==0){
ope[index++]=pop();
}else{
push(cur);
}
}
int[] result=new int[index];
for(int i=0;i<index;i++){
result[i]=ope[i];
}
return result;
}
public void push(int p){
stackPush.push(p);
}
public int pop(){
if(stackPop.isEmpty()==true){
while(stackPush.isEmpty()==false){
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}
}
3.栈逆序
实现一个栈的逆序,但是只能用递归函数和这个栈本身的pop操作来实现,而不能自己申请另外的数据结构。
给定一个整数数组A即为给定的栈,同时给定它的大小n,请返回逆序后的栈。
测试样例:
[4,3,2,1],4
返回:[1,2,3,4]
import java.util.*;
//不使用额外的数据结构,使用递归函数完成栈的反转
//使用数组表示栈结构,一个整数变量n表示栈的大小;因为是栈,所以只能访问数组最后一个元素即栈顶元素,用A[n-1]表示
public class StackReverse {
public int[] reverseStack(int[] A, int n) {
if(n==0){
return A;
}
int bottom=getBottom(A,n);
n--;
reverseStack(A,n);
A[n]=bottom;
return A;
}
//返回栈底元素
public int getBottom(int[] A,int n){
int result=A[n-1];
n--;
//数组第一个元素为栈底元素
if(n==0){
return result;
}
int bottom=getBottom(A,n);
A[n-1]=result;
return bottom;
}
}
4.双栈排序
请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临## 标题 ##时数据,但不得将元素复制到别的数据结构中。
给定一个int[] numbers(C++中为vector<int>),其中第一个元素为栈顶,请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。
测试样例:
[1,2,3,4,5]
返回:[5,4,3,2,1]
import java.util.*;
//双栈排序
public class TwoStacks {
public ArrayList<Integer> twoStacksSort(int[] numbers) {
int size=numbers.length;
ArrayList<Integer> help=new ArrayList<Integer>();
for(int index=0;index<size;index++){
int cur=numbers[index];
if(help.size()==0||cur<=help.get(help.size()-1)){
help.add(cur);
continue;
}else{
int count=0;
while(help.size()>0&&cur>help.get(help.size()-1)){
numbers[index]=help.get(help.size()-1);
help.remove(help.size()-1);
count++;
index--;
}
help.add(cur);
while(count>0){
help.add(numbers[++index]);
count--;
}
}
}
return help;
}
}
5.滑动窗口练习题
有一个整型数组 arr 和一个大小为 w 的窗口从数组的最左边滑到最右边,窗口每次向右边滑一个位置。 返回一个长度为n-w+1的数组res,res[i]表示每一种窗口状态下的最大值。 以数组为[4,3,5,4,3,3,6,7],w=3为例。因为第一个窗口[4,3,5]的最大值为5,第二个窗口[3,5,4]的最大值为5,第三个窗口[5,4,3]的最大值为5。第四个窗口[4,3,3]的最大值为4。第五个窗口[3,3,6]的最大值为6。第六个窗口[3,6,7]的最大值为7。所以最终返回[5,5,5,4,6,7]。
给定整形数组arr及它的大小n,同时给定w,请返回res数组。保证w小于等于n,同时保证数组大小小于等于500。
测试样例:
[4,3,5,4,3,3,6,7],8,3
返回:[5,5,5,4,6,7]
import java.util.*;
//滑动窗口最大值
public class SlideWindow {
public int[] slide(int[] arr, int n, int w) {
LinkedList<Integer> qmax=new LinkedList<Integer>();//双端队列保存数组小标,其中队列头保存着当前的最大值对应的下标
int[] result=new int[n-w+1];
int index=0;
for(int i=0;i<n;i++){
while(qmax.isEmpty()==false&&arr[qmax.peekLast()]<=arr[i]){
qmax.pollLast();
}
qmax.addLast(i);
//如果当前队头的元素不在窗口内了,就弹出
if(qmax.peekFirst()==(i-w)){
qmax.pollFirst();
}
if(i>=(w-1)){
result[index++]=arr[qmax.peekFirst()];
}
}
return result;
}
}
6.数组变树
import java.util.*;
//数组变树
public class MaxTree {
public int[] buildMaxTree(int[] A, int n) {
//遍历数组,找到每个数左边第一个比它大的数,找到每个数右边第一个比它大的数,
int left=-2,right=-2;
int[] result=new int[n];
for(int i=0;i<n;i++){
left=getMax(A,i,true);
right=getMax(A,i,false);
if(left!=-2&&right!=-2){
result[i]=A[left]<A[right]?left:right;
}else {
result[i]=left==-2?right:left;
if(result[i]==-2){
result[i]=-1;
}
}
}
//两个值中最小值是它的父节点如果数组左右比它大的数都是null,那它就是根
return result;
}
public int getMax(int[] A,int curIndex,boolean isLeft){
int maxIndex=curIndex;
if(isLeft==true){
for(int i=curIndex-1;i>=0;i--){
if(A[i]>A[maxIndex]){
maxIndex=i;
break;
}
}
}else{
for(int i=curIndex+1;i<=A.length-1;i++){
if(A[i]>A[maxIndex]){
maxIndex=i;
break;
}
}
}
return maxIndex==curIndex?-2:maxIndex;
}
}
3.JAVA tips
ArrayList 删除元素:remove(index);
双端队列LinkedList qmax = new LinkedList()
双端队列获取队列首个元素或者最后的元素 peekFirst() peekLast()
双端队列弹出队列首个元素 pollFirst() 弹出最尾元素 pollLast()
双端队列添加元素到队尾 addLast(X)