牛客网算法学习记录-队列和栈

来源:互联网 发布:苹果锁屏背单词软件 编辑:程序博客网 时间:2024/05/11 17:29

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

一开始以为是要自己用malloc之类的方法写,但是太麻烦了,然后参考了别人的代码知道原来是用本来就有的栈来写类从而扩充栈的方法。

class Solution {
public:
    void push(int value) {
        if(min_stack.size()==0 || min_stack.top()>=value){
            min_stack.push(value);
        }
        data_stack.push(value);
              
    }
    void pop() {
        int top = data_stack.top();
        data_stack.pop();
        if(min_stack.top() == top){
            min_stack.pop();
        }
    }
    int top() {
        
        return data_stack.top();
        
    }
    int min() {
        return min_stack.top();
    }
    
private:
    stack<int> min_stack;
    stack<int> data_stack;
    
};



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

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

测试样例:
[1,2,3,0,4,0],6
返回:[1,2]
需要注意两点:1.将stack2转移到stack1时,stack1必须是空的;2.stack1必须一次性全部转移到stack2中。

class TwoStack {
public:
    void push(int value){
        
        if(stack2.size()>0){
            stack1.push(value);
        }
        else{
            //int size = stack1.size();
            transStack(stack1.size());
            stack1.push(value);
        }
        
    }
    
    int pop(int value){
        int top ;
        if(stack2.size()>0){
            top = stack2.top();
            stack2.pop();
        }
        else{
            
            transStack(stack1.size());
            if(stack2.size()){
                top = stack2.top();
                stack2.pop();
            }
        }
        return top;
    }
    
    vector<int> twoStack(vector<int> ope, int n) {
        // write code here
        vector<int> result ;
        for(int i = 0 ; i<n;i++){
            if(ope[i]>0){
                push(ope[i]);
            }
            else{
                result.push_back(pop(ope[i]));
            }
        }
        return result;
    }
    
    
    
    void transStack(int size){
        
        for(int i = 0 ; i <size;i++){
            int top = stack1.top();
            stack1.pop();
            stack2.push(top);
        }
    }
    
    
private:
    stack<int> stack1;
    stack<int> stack2;
    
};


个人感觉这个代码不能满足误操作,也就是在模拟队列无元素时,直接POP()也会有一个输出值。


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

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

测试样例:
[4,3,2,1],4
返回:[1,2,3,4]class StackReverse {public:    vector<int> reverseStack(vector<int> A, int n) {        // write code here        reverse(A);        return A;    }        void reverse(vector<int> &A){        if(A.size()==0){            return;        }        int num = getBottom(A);        reverse(A);        A.push_back(num);    }        int getBottom(vector<int> &A){        int cur = A.back();        A.pop_back();        if(A.size() == 0){            return cur;        }        int result = getBottom(A);        A.push_back(cur);        return result;    }};
主要利用递归函数本身放在函数栈内的方式,将每一层和一个stack中的元素进行对应,递归函数返回值则返回最后一个元素,其余元素在同层调出后再重新放入stack中。逆序的主函数则通过在递归中调用获取最后一个元素的函数并存储数值,然后在本层中重新将元素入stack即可。(表述的比较乱。)



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

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

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

思路:先将一个元素移入辅助stack2,然后将新的stack1 的首元素取出,放到T中,和stack2的栈顶元素进行比较,如果stack1<stack2则,stack2出栈存入stack1直到遇到T>stack2的栈顶元素即可放入T到stack2.然后继续遍历,stack1.
即主要是保证每次从stack1中取出元素时,stack2是有序的,然后循环遍历就可将stack1全部放入stack2.


class TwoStacks {
public:
    vector<int> twoStacksSort(vector<int> numbers) {
        // write code here
        vector<int> help;
        while(numbers.size()>0){
            
            int t = numbers[0];
            numbers.erase(numbers.begin());
            while(help.size()!=0){
                if(t < help[0]){
                    int temp = help[0];
                    numbers.insert(numbers.begin(),temp);
                    help.erase(help.begin());     
                }
                else{
                    
                    help.insert(help.begin(),t);
                    break;                   
                }
            }
            if(help.size()==0){
                help.insert(help.begin(),t);
            }
  
        }
        return help;
    }

};


有一个整型数组 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]

class SlideWindow {
public:
    vector<int> slide(vector<int> arr, int n, int w) {
        // write code here
        if(n<=w){    //用于数组长度N不符合窗口宽度的情况
            int max = - (1<<20);
            for(int i = 0 ; i<n;i++){
                if(arr[i]>max)
                    max = arr[i];
            }
            vector<int> help;
            help.push_back(max);
            return help;
        }
        
        vector<int> help;  //记录窗口的值,主键遍历的过程中,比HELP尾元素小的入队,比HELP尾部元素大的则先HELP尾部出队,在对尾部 元素进行比较,直到队列为空或

//插入元素小于队尾元素。
        vector<int> index;//记录help中元素对应的下标,当当前下标与首元素下标的差值超过窗口宽度,则弹出首元素,由于每次窗口右移都更新队列,所以只会出现一次HELP

//首元素下标超过窗口的情况。
        vector<int> result;  //保存输出值
        int count=0;
        for(int i = 0 ; i<n;i++){
            if(help.size()==0){
                help.push_back(arr[i]);
                index.push_back(i);


            }
            else{
                int t;
         
                while(help.size()!=0){  //进行检测,之所以比队尾小的元素入队是为了在窗口后移的时候,防止小的元素成了最大值。
                    t = help.back();
                    if(t<arr[i]){
                        help.pop_back();
                        index.pop_back();
                      
                    }
                    else{
                        help.push_back(arr[i]);
                        index.push_back(i);
                        break;
                    }
                }
                
                if(help.size()==0){
                    help.push_back(arr[i]);
                    index.push_back(i);
                }
                
            }
            count++; //等满足窗口条件时再进行元素的输出
            if(count>=w){
                if( i -w>=index[0]){
                    
                    help.erase(help.begin());
                    index.erase(index.begin());
                }
                
                result.push_back(help[0]);
            }
        }
        return result;
    }
};


别人家的代码:

classSlideWindow {
public:
    vector<int> slide(vector<int> arr, intn, intw) {
        // write code here
        list<int> qmax;
        vector<int> res;
        for(inti = 0; i < n; i++)
        {
            if(!qmax.empty()) {
                while(!qmax.empty() && arr[i] >= arr[qmax.back()])
                    qmax.pop_back();
            }
            if(i < w -1)
                qmax.push_back(i);
            else{
                if(!qmax.empty() && qmax.front() < i - w + 1)
                    qmax.pop_front();
                qmax.push_back(i);
                res.push_back(arr[qmax.front()]);
            }
        }
        returnres;
    }
};


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

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

测试样例:
[3,1,4,2],4
返回:[2,0,-1,2]
写错了。。
我的错误代码:
class MaxTree {
public:
    vector<int> buildMaxTree(vector<int> A, int n) {
        // write code here
        vector<int> leftMaxIndex(n,-3);
        vector<int> rightMaxIndex(n,-3);
        vector<int> result(n,-3);
        stack<int> index;
        for(int i = 0;i<n;i++){
            if(index.empty()){
                index.push(i);
            }
            else{
                int contain = index.top();
                while(A[contain]<A[i]&&!index.empty()){
                    index.pop();
                    rightMaxIndex[contain] = i;
                    contain = index.top();
                }
                if(index.empty()){
                    index.push(i);
                }
                
                else if(A[contain]<A[i]){
                    rightMaxIndex[contain] = i;
                }
                else if (A[contain]>A[i]){
                    index.push(i);
                leftMaxIndex[i] = contain;
                }
            }
        }
        while(!index.empty()){
            index.pop();
        }
        
        for(int i = n -1 ;i>=0;i--){
            
            if(index.empty()){
                index.push(i);
            }
            else{
                int contain = index.top();
                while(A[contain]<A[i]&&!index.empty()){
                    index.pop();
                    leftMaxIndex[contain] = i ;
                    contain = index.top();
                }
                if(A[contain]<A[i]){
                    leftMaxIndex[contain] = i;
                }
                else if (A[contain]>A[i]){
                    index.push(i);
                    rightMaxIndex[i] = contain;
                }
            } 
        }
        for(int i = 0 ; i<n;i++){
            int output = indexOfMax(leftMaxIndex[i],rightMaxIndex[i],A);
            result[i] = output;
        }
        return result;
    }


    int indexOfMax(int left,int right,vector<int> A){
        if(left == -3 && right == -3){
            return -1;
        }
        if(left == -3){
            return right;
        }
        if(right == -3){
            return left;
        }
        if(A[left]>A[right]){
            return right;
        }
        else{
            return left;
        }
    }
};

别人家的代码:

classMaxTree {
public:
    vector<int> buildMaxTree(vector<int> A, intn) {
        // write code here
        vector<int> res;
        intleftmax, rightmax;
 
        for(inti = 0; i < n; ++i){
            leftmax = rightmax = -1;
            for(intj = i; j >= 0; --j){
                if(A[j] > A[i]){
                    leftmax = j;
                    break;
                }
            }
            for(intj = i; j < n; ++j){
                if(A[j] > A[i]){
                    rightmax = j;
                    break;
                }
            }
            if(leftmax == -1&& rightmax == -1)
                res.push_back(-1);
            if(leftmax == -1&& rightmax != -1)
                res.push_back(rightmax);
            if(leftmax != -1&& rightmax == -1)
                res.push_back(leftmax);
            if(leftmax != -1&& rightmax != -1){
                intmin = A[leftmax] > A[rightmax] ? rightmax : leftmax;
                res.push_back(min);
            }
        }
        returnres;
    }
};

0 0