您的位置:首页 > 职场人生

程序员代码面试指南(栈和队列)

2018-03-06 15:31 561 查看
一.由两个栈组成的队列
1.首先往一个栈中(定义为stackPush)压入数据,可以作为队列的进队操作(队列是在对头出列,对尾进列)
2.将stackPush中的数据依次弹出并push到另一个栈中(定义为stackPop),依次弹出stackPop栈中的数据即可//定义一个入栈
Stack<Integer> stackPush=new Stack<>();
//定义一个出栈
Stack<Integer> stackPop=new Stack<>();

//实现队列的入队
public void add(int num) {
stackPush.push(num);
}

//实现队列的pool
public int pool() {
if(stackPush.isEmpty()) {
throw new RuntimeException("队列为空");
}
if(stackPop.isEmpty()) {
while(!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}

//实现队列的peek
public int peek() {
if(stackPush.isEmpty()) {
throw new RuntimeException("队列为空");
}
if(stackPop.isEmpty()) {
while(!stackPush.isEmpty()) {
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}

二.用一个栈实现另一个栈的排序
申请一个辅助栈(定义为tempStack),将原始栈中(定义为stack)的数组压入tempStack栈中,遵循以下原则:

1.如果stack中的栈顶元素小于tempSatck的栈顶元素,则直接压入tempSatck栈中
2.如果stack中的栈顶元素大于tempSatck的栈顶元素,先将stack栈的栈顶元素弹出,然后将tempStack中小于stack栈的栈顶元素的值依次压入stack中,接着从步骤1开始判断,直到stack空为止
3.将tempStack栈中的数依次压入stack中,则得到从大到小排序的栈(从顶到底--从大到小)public void sortStackByStack(Stack<Integer> stack) {

//申请一个辅助栈
Stack<Integer> temp=new Stack<>();
while(!stack.isEmpty()) {
int value=stack.pop(); //表示stack栈顶弹出的值
while(!temp.isEmpty()&&value>temp.peek()) {
stack.push(temp.pop());
}
temp.push(value);
}
while(!temp.isEmpty()) {
stack.push(temp.pop());
}
}

三.生成窗口最大值数组
1.基本方法
可以定义一个index,表示窗口的首位置,随着窗口的移动,index++,找出index到index+w之间的最大值并进入到数组中即可
时间复杂度:由于计算每个窗口的最大值的时间复杂度为O(w),总共需要移动n-w+1次,因此总的时间复杂度为O(nw)ArrayList<Integer> list=new ArrayList<>();

public ArrayList<Integer> getMaxWindow(int[] array,int w) {
int index=0;
while(index+w<=array.length) {
int max=array[index];
for(int i=index;i<index+w;i++) {
if(array[i]>max) {
max=array[i];
}
}
list.add(max);
index++;
}
return list;
}

public static void main(String[] args) {
ArrayList<Integer> resultList=new ArrayList<>();
int[] array=new int[] {4,3,5,4,3,3,6,7};
int w=3;
resultList=new Example4().getMaxWindow(array, w);
for(int i:resultList) {
System.out.print(i+" ");
}
}2.利用链表,将窗口的最大值保持在链表的头部,具体讲解可以参看《程序员代码面试指南》 //利用链表
public int[] getMaxWindow2(int[] array,int w){
LinkedList<Integer> list=new LinkedList<>();
int[] result=new int[array.length-w+1];
int index=0;
for(int i=0;i<array.length;i++) {
//当链表不为空时且当前遍历的元素值要大于链表的尾部元素的值,则将链表尾部元素弹出
while(!list.isEmpty()&&array[list.peekLast()]<=array[i]) {
list.pollLast();
}
list.add(i); //否则就向尾部添加值
if(list.peekFirst()==i-w) { //表示当前对头元素已经过期
list.pollFirst();
}
if(i>=w-1) { //表示已经达到了窗口最大位置
result[index]=array[list.peekFirst()];
index++;
}
}
return result;
}时间复杂度为O(N)
四.求直方图的最大矩形面积大小
1.直接遍历的方法,找出每一块分别向左和向右能扩展的边界,求出以每一块为中心能达到的最大面积//直接遍历的方法,依次求出每个块能向左向右扩展的边界
public int maxArea1(int[] height) {
int maxArea=0;
int temp=0;
int k=0;int j=0;
for(int i=0;i<height.length;i++) {
//向左扩展
for(j=i;j>=0;j--) {
if(height[j]<height[i]) {
break;
}

a190
}
//向右扩展
for( k=i;k<height.length;k++) {
if(height[k]<height[i]) {
break;
}
}
temp=(k-j-1)*height[i];
maxArea=Math.max(temp, maxArea);
}
return maxArea;
}2.利用栈的思想,具体讲解可以参看《程序员代码面试指南》//利用栈和动态规划的思想
public int maxArea2(int[] height) {
int maxArea=0;
Stack<Integer> stack=new Stack<>();
for(int i=0;i<height.length;i++) {
while(!stack.isEmpty()&&height[i]<=height[stack.peek()]) {
int j=stack.pop(); //弹出当前栈顶元素
int k=stack.isEmpty()?-1:stack.peek(); //弹出后当前栈顶的元素,可以理解为栈为空时的栈顶元素为-1
int currentArea=(i-k-1)*height[j]; //以栈顶元素为中心的最大矩形面积
maxArea=Math.max(maxArea, currentArea);
}
stack.push(i);
}

//当遍历完之后,若栈内还有元素,则全部弹出
while(!stack.isEmpty()){
int j=stack.pop(); //弹出当前栈顶元素
int k=stack.isEmpty()?-1:stack.peek(); //当前栈顶元素,可以理解为栈为空时的栈顶元素为-1
int currentArea=(height.length-k-1)*height[j];
maxArea=Math.max(maxArea, currentArea);
}
return maxArea;

}五.最大值减去最小值小于等于num的子数组的数量public int getNum(int[] arr,int k) {
int res = 0;
int left = 0;//左边界
int right = 0;//右边界
LinkedList<Integer> qmin= new LinkedList<Integer>();//最小值队列 递增
LinkedList<Integer> qmax= new LinkedList<Integer>();//最大值队列 递减
while(left<arr.length){
while (right<arr.length){
while(!qmin.isEmpty()&&arr[qmin.peekLast()]>=arr[right]){//
qmin.pollLast();
}
qmin.addLast(right);
while(!qmax.isEmpty()&&arr[qmax.peekLast()]<=arr[right]){
qmax.pollLast();
}
qmax.addLast(right);
if(arr[qmax.peekFirst()]-arr[qmin.peekFirst()]>k){//不符合要求

break;
}
right++;//符合要求 右边界累加 子数组累加
}
//左边界移动之前先判断最小值 和 最大值队列中第一个是否为左边界 如果相等则移除
if(left==qmin.peekFirst()){
qmin.pollFirst();
}
if(left==qmax.peekFirst()){
qmax.pollFirst();
}
res += right-left; //清算之前一共有多少个子数组符合要求
left++;
}
return res;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: