队列和栈

1可查询最值的栈

定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数。

方法一:dataStack和minStack,只有当前数小于等于minStack的栈顶时,该数放入minStack

           弹出时,dataStack先弹出,当前值等于minStack栈顶时弹出

import java.util.Stack;

public class Solution {
    private Stack<Integer> dataStack=new Stack<Integer>();
    private Stack<Integer> minStack=new Stack<Integer>();
    
    public void push(int node){
        dataStack.push(node);
        if(minStack.isEmpty()||minStack.peek()>=node){
            minStack.push(node);
        }
    }
    
    public void pop(){
        if(dataStack.isEmpty()){
            throw new RuntimeException("Your stack is empty!");
        }
        if(dataStack.peek()==minStack.peek()){
            minStack.pop();
        }
        dataStack.pop();
    }
    
    public int top(){
        return dataStack.peek();        
    }
    
    public int min(){
        if(minStack.isEmpty()){
            throw new RuntimeException("Your stack is empty!");
        }
        return minStack.peek();
    }
}

方法二:dataStack和minStack,当前数和minStack栈顶元素比较,较小的压入minStack

           弹出时,dataStack和minStack同步弹出

import java.util.Stack;

public class Solution {
    private Stack<Integer> dataStack=new Stack<Integer>();
    private Stack<Integer> minStack=new Stack<Integer>();
    
    public void push(int node){
        dataStack.push(node);
        if(minStack.isEmpty()||minStack.peek()>=node){
            minStack.push(node);
        }else{
            minStack.push(minStack.peek());
        }
    }
    
    public void pop(){
        if(dataStack.isEmpty()){
            throw new RuntimeException("Your stack is empty!");
        }
        //if(dataStack.peek()==minStack.peek()){
        //    minStack.pop();
        //}
        minStack.pop();
        dataStack.pop();
    }
    
    public int top(){
        return dataStack.peek();        
    }
    
    public int min(){
        if(minStack.isEmpty()){
            throw new RuntimeException("Your stack is empty!");
        }
        return minStack.peek();
    }
}

2双栈队列

编写一个类,只能用两个栈结构实现队列,支持队列的基本操作(push,pop)。

给定一个操作序列ope及它的长度n,其中元素为正数代表push操作,为0代表pop操作,保证操作序列合法且一定含pop操作,请返回pop的结果序列。

测试样例:
[1,2,3,0,4,0],6
返回:[1,2]

思路:pushStack和popStack,将pushStack中元素全部倒入popStack中,
两个重要的注意点:1.如果pushStack要往popStack中倒入数据,那么要把pushStack中的所有数据一次性倒完;
2.如果popStack中有数据,则不可能发生倒数据的行为。
import java.util.Stack;

public class Main2 {
    public int[] twoStack(int[] ope,int n){
        Stack<Integer> pushStack=new Stack<Integer>();
        Stack<Integer> popStack=new Stack<Integer>();
        int count=0;
        for(int i=0;i<n;i++){
            if(ope[i]>0){
                pushStack.push(ope[i]);
            }else if(ope[i]==0){
                count++;
            }
        }
        int[] a=new int[count];
        while(!pushStack.isEmpty()){
            popStack.push(pushStack.pop());
        }
        int i=0;
        while(count>=0){
            a[i++]=popStack.pop();
            count--;
        }
        return a;
    }
}

3栈的反转

实现一个栈的逆序,但是只能用递归函数和这个栈本身的pop操作来实现,而不能自己申请另外的数据结构。

给定一个整数数组A即为给定的栈,同时给定它的大小n,请返回逆序后的栈。

测试样例:
[4,3,2,1],4
返回:[1,2,3,4]

import java.util.*;

public class StackReverse {
    public int[] reverseStack(int[] A,int n){
        Stack<Integer> stack=new Stack<Integer>();
        for(int i=0;i<n;i++){
            stack.push(A[i]);
        }
        reverse(stack);
        for(int i=n-1;i>=0;i--){
            A[i]=stack.pop();
        }
        return A;
        
    }
    
    public void reverse(Stack<Integer> stack){
        if(stack.isEmpty()){
            return;
        }
        int i=get(stack);
        reverse(stack);
        stack.push(i);
    }
    
    public int get(Stack<Integer> stack){
        int result=stack.pop();
        if(stack.isEmpty()){
            return result;
        }else{
            int last=get(stack);
            stack.push(result);
            return last;
        }
    }
}

牛客网上的代码

import java.util.*;
 
public class StackReverse {
    public int[] reverseStack(int[] A, int n) {
        // write code here
        if(n==0){
            return A;
        }
       int a=get(A,n);
       n--;
       reverseStack(A,n);
       A[n]=a;
       return A;
    }      
   public int get(int[] A,int n){
        int result=A[n-1];
        n--;
        if(n==0){
            return result;
        }
        else{
            int last=get(A,n);
            A[n-1]=result;
            return last;
        }
    }
}

4双栈排序

请编写一个程序,按升序对栈进行排序(即最大元素位于栈顶),要求最多只能使用一个额外的栈存放临时数据,但不得将元素复制到别的数据结构中。

给定一个int[] numbers(C++中为vector<int>),其中第一个元素为栈顶,请返回排序后的栈。请注意这是一个栈,意味着排序过程中你只能访问到第一个元素。

测试样例:
[1,2,3,4,5]
返回:[5,4,3,2,1]

numbers
  0
   
  n
help

  0
   
  n

import java.util.*;
 
public class TwoStacks {
    public ArrayList<Integer> twoStacksSort(int[] numbers) {
                int[] help = new int[numbers.length];
                int n = numbers.length;
                int i = 0, j = n;//栈的当前指针
                int cur;
                while (i < n) {
                        //++为出栈,--为进栈
                        //弹出栈中的第一个元素,下移index
                        cur = numbers[i++];
 
                        if (j == n) {
                                // 将弹出元素压入help栈顶
                                help[--j] = cur;
                        } else if (cur <= help[j]) {
                                // 将弹出元素压入help栈顶
                                help[--j] = cur;
                        } else if (cur > help[j]) {
                                // 弹出help栈中的元素,并将其压入到主栈栈顶,直到cur小于等于help栈顶元素
                                while (j < n && cur > help[j]) {
                                        numbers[--i] = help[j++];
                                }
                                // 将弹出元素压入help栈顶
                                help[--j] = cur;
                        }
 
                }
                numbers[0] = help[n - 1];
 
 
                ArrayList<Integer> list = new ArrayList<>();
                for (int m = 0; m < n; m++) {
                        list.add(help[n - m - 1]);
                }
                return list;}
     
}

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) {
        // write code here
        int[] res=new int[n-w+1];
        int index=0;
        for(int i=0;i<=n-w;i++){
            res[index++]=getMax(arr,i,i+w);
        }
        return res;
    }
     
    //求数组最大值并返回
    public int getMax(int[] arr,int start,int end){
        int max=arr[start];
        for(int i=start;i<end;i++){
            if(arr[i]>max){
                max=arr[i];
            }
        }
        return max;
    }
}

 

import java.util.*;
 
public class SlideWindow {
    public int[] slide(int[] arr, int n, int w) {
        // write code here
        if(w>n||arr==null)
            return null;
        int front = 0, back = 0,left = 0;
        int[] result = new int[n-w+1];
        int[] qmax = new int[n];
        for(int i=0; i<n; i++){
             
            while(back<front&&arr[qmax[front-1]]<arr[i])
                  front--;
            qmax[front++] = i;
             
            if(left+w-1==i){
                //达到窗口长度
                result[left] = arr[qmax[back]];
                left++;
            }
            if(qmax[back]+w-1==i){
                //队尾过期
                back++;
            }
        } 
        return result;
    }
}

6数组变树

对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree,MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应,同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。现有一建树方法,对于数组中的每个元素,其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个数中更小的一个。若两边都不存在比它大的数,那么它就是树根。请设计O(n)的算法实现这个方法。

给定一个无重复元素的数组A和它的大小n,请返回一个数组,其中每个元素为原数组中对应位置元素在树中的父亲节点的编号,若为根则值为-1。

测试样例:
[3,1,4,2],4
返回:[2,0,-1,2]

import java.util.*;
 
public class MaxTree {
   public int[] buildMaxTree(int[] A, int n) {
        int[] res = new int[A.length];
       for(int i=0;i<A.length;i++) {
           int j = i-1;
           int left = -1,right = -1;
           while(j>=0 && A[i]>A[j]) {
               j--;
           }
           if(j>=0) {
               left = j;
           }
           j = i+1;
           while(j<A.length && A[i]>A[j]) {
               j++;
           }
           if(j<A.length) {
               right = j;
           }
           if(left!=-1 && right !=-1) {
               if(A[left]>A[right]) {
                   res[i] = right;
               } else {
                   res[i] = left;
               }
           } else {
               if(left==-1) {
                   res[i] = right;
               } else if(right==-1) {
                   res[i] = left;
               } 
           }
       }
       return res;
     
    }
}

 



 

posted @ 2017-04-26 17:08  临江仙zhe  阅读(72)  评论(0)    收藏  举报