劍指offer刷題(一)(1-20)題

由於之前要準備paper以及研電賽,好久沒有更新了,paper已經投了個會議了,然後研電賽只拿到了西北賽區人工智能組的二等獎,沒能晉級國賽有點遺憾。廢話不多說,準備秋招了,刷點編程題練練手。每題都有思路,有些是參考的,會註明出處。題目順序參照牛客網,語言選擇C++,因爲C++速度確實快。

1 二維數組的查找

在一個二維數組中(每個一維數組的長度相同),每一行都按照從左到右遞增的順序排序,每一列都按照從上到下遞增的順序排序。請完成一個函數,輸入這樣的一個二維數組和一個整數,判斷數組中是否含有該整數。

class Solution {
public:
    /**
    利用
    每一行都按照從左到右遞增的順序排序
    每一列都按照從上到下遞增的順序排序
    如果 xx 小於target,則 xx 左邊的數一定都小於target,我們可以直接排除當前一整行的數;
    如果 xx 大於target,則 xx 下邊的數一定都大於target,我們可以直接排序當前一整列的數;
    參考:https://www.acwing.com/solution/AcWing/content/702/
    */
    bool Find(int target, vector<vector<int> > a) {
        //如果a爲空 直接返回false
        if(a.empty()||a[0].empty())return false;
        int i = 0, j = a[0].size() - 1;//要從右上角往左下角找
        while(i < a.size() && j >= 0){
            if(a[i][j] == target)return true;//找到直接返回
            if(a[i][j] > target) j--;//列往左邊移動
            else i++;//行往下移動找
        }
        return false;
    }
};

2 替換空格

請實現一個函數,將一個字符串中的每個空格替換成“%20”。例如,當字符串爲We Are Happy.則經過替換之後的字符串爲We%20Are%20Happy。


class Solution {
public:
	void replaceSpace(char *str,int length) {
        if(str == NULL) return; //如果是空 直接返回
        //空格數 原始串的長 新串的長
        int blanks = 0, len = 0, newlen = 0;
        for(int i = 0;str[i]!='\0';i++){
            len++;
            if(str[i]==' ')
                blanks++;
        }
        //新串的長 每次替換 多增加兩個字符
        newlen = len + 2*blanks;
        
        //如果新串的長大於length 直接返回
        if(newlen + 1 > length)return;
        
        //str1指針指向舊串的最後一個字符
        char * str1 = str + len;
        
        //str2指針指向新串的最後一個字符
        char * str2 = str + newlen;
        
        //從後向前自制舊串 並替換空格
        while(str1 != str2){
            if(*str1 == ' '){
                *str2 -- = '0';
                *str2 -- = '2';
                *str2 -- = '%';
            }
            else
                *str2 -- = *str1;
            --str1;
        }
        
	}
};

3 從尾到頭打印鏈表

輸入一個鏈表,按鏈表值從尾到頭的順序返回一個ArrayList。

/**
*  struct ListNode {
*        int val;
*        struct ListNode *next;
*        ListNode(int x) :
*              val(x), next(NULL) {
*        }
*  };
   沒有什麼要求,直接遍歷一次鏈表,每次向vector.begin()處插入就行了
*/
class Solution {
public:
    vector<int> printListFromTailToHead(ListNode* head) {
        vector<int> res;
        while(head){
            res.insert(res.begin(),head->val);
            head = head->next;
        }
        return res;
    }
};

4 重建二叉樹

輸入某二叉樹的前序遍歷和中序遍歷的結果,請重建出該二叉樹。假設輸入的前序遍歷和中序遍歷的結果中都不含重複的數字。例如輸入前序遍歷序列{1,2,4,7,3,5,6,8}和中序遍歷序列{4,7,2,1,5,3,8,6},則重建二叉樹並返回。

/**
 * Definition for binary tree
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 算法
(遞歸) O(n)O(n)
遞歸建立整棵二叉樹:先遞歸創建左右子樹,然後創建根節點,並讓指針指向兩棵子樹。

具體步驟如下:

先利用前序遍歷找根節點:前序遍歷的第一個數,就是根節點的值;
在中序遍歷中找到根節點的位置 kk,則 kk 左邊是左子樹的中序遍歷,右邊是右子樹的中序遍歷;
假設左子樹的中序遍歷的長度是 ll,則在前序遍歷中,根節點後面的 ll 個數,是左子樹的前序遍歷,剩下的數是右子樹的前序遍歷;
有了左右子樹的前序遍歷和中序遍歷,我們可以先遞歸創建出左右子樹,然後再創建根節點;

時間複雜度分析
我們在初始化時,用哈希表(unordered_map<int,int>)記錄每個值在中序遍歷中的位置,
這樣我們在遞歸到每個節點時,在中序遍歷中查找根節點位置的操作,
只需要 O(1)O(1) 的時間。此時,創建每個節點需要的時間是 O(1)O(1),所以總時間複雜度是 O(n)O(n)。

參考:https://www.acwing.com/solution/AcWing/content/706/
 */
class Solution {
public:
    
    TreeNode* dfs(unordered_map<int,int> &pos,vector<int> &pre, vector<int> &vin, int pl, int pr, int vl, int vr){
        if(pl > pr)return 0;
        int k = pos[pre[pl]] - vl ;//k的左邊爲左子樹,右邊爲右子樹
        TreeNode* root = new TreeNode(pre[pl]);//創建根
        root->left = dfs(pos, pre, vin, pl + 1, pl + k, vl, vl + k - 1);//遞歸創建左子樹,更新下次pre和vin
        root->right = dfs(pos, pre, vin, pl + k + 1, pr,  vl + k + 1, vr);//遞歸創建右子樹,更新下次pre和vin
        return root;
    }
    TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
        int n = pre.size();
        unordered_map<int,int> pos;//記錄中序遍歷的位置
        for(int i = 0; i < n; i++){
            pos[vin[i]] = i;
        }
        return dfs(pos, pre, vin, 0, n - 1, 0, n - 1);
    }
    
};

5 用棧實現隊列

用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素爲int類型。

/**
用兩個棧 一個緩存用
當操作時 先把主棧的數據先全部放到緩存
然後再pop
完成後放到主棧
**/

class Solution
{
public:
    void copy(stack<int> &a, stack<int> &b) {
        while (a.size()) {
            b.push(a.top());
            a.pop();
        }
    }
    void push(int node) {
        stack1.push(node);
    }
    int pop() {
        copy(stack1,stack2);
        int res = stack2.top();
        stack2.pop();
        copy(stack2,stack1);
        return res;
    }

private:
    stack<int> stack1;//主棧
    stack<int> stack2;//緩存棧
};

6 旋轉數組中最小的數字

把一個數組最開始的若干個元素搬到數組的末尾,我們稱之爲數組的旋轉。 輸入一個非減排序的數組的一個旋轉,輸出旋轉數組的最小元素。 例如數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉,該數組的最小值爲1。 NOTE:給出的所有元素都大於0,若數組大小爲0,請返回0。

/**
數組{3,4,5,1,2}爲{1,2,3,4,5}的一個旋轉
可以看出
因爲旋轉前數組是遞增
旋轉後有一個這個遞增就斷了
相當於找到一個數比第一個數小的情況
就可以返回這個數
**/
class Solution {
public:
    int minNumberInRotateArray(vector<int> rotateArray) {
        if(!rotateArray.size())return 0;
        int res = rotateArray[0];
        for(int i = 1; i < rotateArray.size(); i++){
            if(rotateArray[i] < res)return rotateArray[i];
        }
        return res;
    }
};

7 斐波那契數列

大家都知道斐波那契數列,現在要求輸入一個整數n,請你輸出斐波那契數列的第n項(從0開始,第0項爲0)。n<=39。

/**
這個沒什麼好說的
建議用遞推
除非面試官要求 否則不要用遞歸
**/
class Solution {
public:
    int Fibonacci(int n) {
        if(n == 0) return 0;
        if(n == 1) return 1;
        int first = 0, second = 1, third = 0;
        while(n--){
            third = first + second;
            first = second;
            second = third;
        }
        return first;
    }
};

8 跳臺階

一隻青蛙一次可以跳上1級臺階,也可以跳上2級。求該青蛙跳上一個n級的臺階總共有多少種跳法(先後次序不同算不同的結果)。

/**
假設處於當前臺階
那麼從其他臺階跳上來的
要麼從前一個臺階跳上來 要麼從前面第2個跳過來
那麼 跳到當前臺階的就有f(n-1) + f(n - 2)
**/
class Solution {
public:
    int jumpFloor(int n) {
        if(n == 1) return 1;
        if(n == 2) return 2;
        return jumpFloor(n - 1) + jumpFloor(n - 2);
    }
};

9 變態跳臺階

一隻青蛙一次可以跳上1級臺階,也可以跳上2級……它也可以跳上n級。求該青蛙跳上一個n級的臺階總共有多少種跳法。

/**
因爲n級臺階,第一步有n種跳法:跳1級、跳2級、到跳n級
跳1級,剩下n-1級,則剩下跳法是f(n-1)
跳2級,剩下n-2級,則剩下跳法是f(n-2)
所以f(n)=f(n-1)+f(n-2)+...+f(1)
因爲f(n-1)=f(n-2)+f(n-3)+...+f(1)
所以f(n)=2*f(n-1)

假設
f(1) = 1;
所以:
f(2)=1+f(1)=1+1=2=2^1;
f(3)=1+f(2)+f(1)=1+2+1=4=2^2;
f(4)=1+f(3)+f(2)+f(1)=1+4+2+1=8=2^3;
......
歸納:
f(n) = 2^(n-1);(n>=1的整數)
**/
class Solution {
public:
    int jumpFloorII(int number) {
        int a = 1; 
        return a << (number - 1);//左移乘2 右移除2 如在折半查找中 可以 int mid = (l + r) >> 1
    }
};

10  矩形覆蓋

我們可以用2*1的小矩形橫着或者豎着去覆蓋更大的矩形。請問用n個2*1的小矩形無重疊地覆蓋一個2*n的大矩形,總共有多少種方法?

class Solution {
public:
    int rectCover(int n) {
        if(n == 1) return 1;
        if(n == 2) return 2;
        int first = 1, second = 2, third = 0;
        for(int i=3;i<=n;i++){
            third = first + second;
            first = second;
            second = third;
        }
        return third;
    }
};

11 二進制中1的個數

輸入一個整數,輸出該數二進制表示中1的個數。其中負數用補碼錶示。

/**
(位運算) O(logn)O(logn)
迭代進行如下兩步,直到 nn 變成0爲止:

如果 nn 在二進制表示下末尾是1,則在答案中加1;
將 nn 右移一位,也就是將 nn 在二進制表示下的最後一位刪掉;
這裏有個難點是如何處理負數。
在C++中如果我們右移一個負整數,系統會自動在最高位補1,這樣會導致 nn 永遠不爲0,就死循環了。
解決辦法是把 nn 強制轉化成無符號整型,這樣 nn 的二進制表示不會發生改變,但在右移時系統會自動在最高位補0。

時間複雜度
每次會將 nn 除以2,最多會除 lognlogn 次,所以時間複雜度是 O(logn)O(logn)。

參考大神:https://www.acwing.com/solution/AcWing/content/732/
**/
class Solution {
public:
     int  NumberOf1(int n) {
         int res = 0;
         unsigned int u = n;
         while(u) res += u & 1, u >>= 1;
         return res;
     }
};

12 數值的整數次方

給定一個double類型的浮點數base和int類型的整數exponent。求base的exponent次方。

/**
求冪就是n個base相乘
如果是負數,取倒數
**/
class Solution {
public:
    double Power(double base, int exponent) {
        double res = 1;
        for(int i = 0; i < abs(exponent); i++)
            res *= base;
        if(exponent < 0)
            res = 1 / res;
        return res;
    }
};

13 調整數組順序使奇數位於偶數前面

輸入一個整數數組,實現一個函數來調整該數組中數字的順序,使得所有的奇數位於數組的前半部分,所有的偶數位於數組的後半部分,並保證奇數和奇數,偶數和偶數之間的相對位置不變。

/**
由於沒有內存申請限制
直接用兩個隊列 一個裝奇數 一個裝偶數
依次按放到原來的數組
**/

class Solution {
public:
    void reOrderArray(vector<int> &array) {
        queue<int> s1,s2;
        for(auto it: array){
            if(it % 2 == 0)
                s2.push(it);
            else s1.push(it);
        }
        for(int i = 0; i < array.size(); i++){
            if(!s1.empty()){
                array[i] = s1.front();
                s1.pop();
            }
            else{
                array[i] = s2.front();
                s2.pop();
            }
        }   
    }
};

14 鏈表中倒數第k個結點

輸入一個鏈表,輸出該鏈表中倒數第k個結點。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
    先算出鏈表的長度n
    倒數第k個結點即爲順數第n-k個結點
    
    
};*/
class Solution {
public:
    ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {
        int len = 0;
        auto cur = pListHead;
        while(cur){
            len++;
            cur = cur->next;
        }
        if(pListHead == NULL || k > len || k < 1)return NULL;
        int i = len - k;
        cur = pListHead;
        while(i--){
            cur = cur->next;
        }
        return cur;
    }
};

15 反轉鏈表

輸入一個鏈表,反轉鏈表後,輸出新鏈表的表頭

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};*/
class Solution {
public:

    ListNode* ReverseList(ListNode* pHead) {
        ListNode *pre = NULL, *next = NULL;
        
        while(pHead){
            //做循環,如果當前節點不爲空的話,始終執行此循環,此循環的目的就是讓當前節點從指向next到指向pre
            //如此就可以做到反轉鏈表的效果
            //先用next保存head的下一個節點的信息,保證單鏈表不會因爲失去head節點的原next節點而就此斷裂
            next = pHead->next;//記錄當前結點的下一個結點

            //保存完next,就可以讓head從指向next變成指向pre了
            pHead->next = pre;

            //head指向pre後,就繼續依次反轉下一個節點
            //讓pre,head,next依次向後移動一個節點,繼續下一次的指針反轉
            pre = pHead;
            pHead = next;
        }
        //如果head爲null的時候,pre就爲最後一個節點了,但是鏈表已經反轉完畢,pre就是反轉後鏈表的第一個節點
        //直接輸出pre就是我們想要得到的反轉後的鏈表
        return pre;
    }
};

16 合併兩個有序鏈表

輸入兩個單調遞增的鏈表,輸出兩個鏈表合成後的鏈表,當然我們需要合成後的鏈表滿足單調不減規則。

/*
struct ListNode {
	int val;
	struct ListNode *next;
	ListNode(int x) :
			val(x), next(NULL) {
	}
};
沒有什麼可說的
就像合併兩個有序數組
*/
class Solution {
public:
    ListNode* Merge(ListNode* p1, ListNode* p2)
    {
        auto d = new ListNode(-1);//虛擬頭結點
        auto t = d;
        while(p1&&p2){
            if(p1->val < p2->val){//小的先排
                t->next = p1;
                p1 = p1->next;
                t = t->next;
            }
            else{
                t->next = p2;
                p2 = p2->next;
                t = t->next;
            }
                
        }
        if(p1)t->next = p1;//如果還有直接接到t的屁股後面
        if(p2)t->next = p2;
        return d->next;
    }
};

17 樹的子結構

輸入兩棵二叉樹A,B,判斷B是不是A的子結構。(ps:我們約定空樹不是任意一個樹的子結構)

/*
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
    
算法
(二叉樹,遞歸) O(nm)O(nm)
代碼分爲兩個部分:

遍歷樹A中的所有非空節點R;
判斷樹A中以R爲根節點的子樹是不是包含和樹B一樣的結構,且我們從根節點開始匹配;
對於第一部分,我們直接遞歸遍歷樹A即可,遇到非空節點後,就進行第二部分的判斷。

對於第二部分,我們同時從根節點開始遍歷兩棵子樹:

如果樹B中的節點爲空,則表示當前分支是匹配的,返回true;
如果樹A中的節點爲空,但樹B中的節點不爲空,則說明不匹配,返回false;
如果兩個節點都不爲空,但數值不同,則說明不匹配,返回false;
否則說明當前這個點是匹配的,然後遞歸判斷左子樹和右子樹是否分別匹配即可;
時間複雜度
最壞情況下,我們對於樹A中的每個節點都要遞歸判斷一遍,每次判斷在最壞情況下需要遍歷完樹B中的所有節點。
所以時間複雜度是 O(nm)O(nm),其中 nn 是樹A中的節點數, mm 是樹B中的節點數。


參考大神:https://www.acwing.com/solution/AcWing/content/745/

};*/
class Solution {
public:
    bool isSubtree(TreeNode* r1, TreeNode* r2){
        if(!r2)return true;
        if(!r1 || r1->val != r2->val)return false;
        return isSubtree(r1->left, r2->left) && isSubtree(r1->right, r2->right);
    }
    bool HasSubtree(TreeNode* r1, TreeNode* r2)
    {
        if(!r1 || !r2)return false;
        if(isSubtree(r1, r2))return true;
        return HasSubtree(r1->left, r2) || HasSubtree(r1->right, r2);
    }
};

18 二叉樹的鏡像

操作給定的二叉樹,將其變換爲源二叉樹的鏡像。

輸入描述:

二叉樹的鏡像定義:源二叉樹 
    	    8
    	   /  \
    	  6   10
    	 / \  / \
    	5  7 9 11
    	鏡像二叉樹
    	    8
    	   /  \
    	  10   6
    	 / \  / \
    	11 9 7  5
/*
沒什麼好說的
直接交換當前結點的左右孩子
如果當前結點還有左右孩子
分別遞歸交換
直到遞歸結束
struct TreeNode {
	int val;
	struct TreeNode *left;
	struct TreeNode *right;
	TreeNode(int x) :
			val(x), left(NULL), right(NULL) {
	}
};*/
class Solution {
public:
    void Mirror(TreeNode *r) {
        if(!r)return;//沒有左右孩子則直接返回
        swap(r->left,r->right);//交換左右孩子
        Mirror(r->left);//遞歸,繼續遍歷左子樹
        Mirror(r->right);//遞歸,繼續遍歷右子樹
    }
};

19 順時針打印矩陣

輸入一個矩陣,按照從外向裏以順時針的順序依次打印出每一個數字,例如,如果輸入如下4 X 4矩陣: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 則依次打印出數字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.

/**
分別得到行和列的開始和末尾索引
首先遍歷完當前行後 開始行++
然後列從開始行索引開始遍歷後 列--
末尾行從末尾列往回遍歷
開始列從末尾行到開始行往回遍歷
直到list長度和size一樣 結束循環

由於沒有其他空間,不算題目要的list的話 空間複雜度O(1) 時間複雜度O(n^2)

**/
class Solution {
public:
    vector<int> printMatrix(vector<vector<int> > matrix) {
        vector<int> list;
        if(matrix.size() == 0) return list;
        //水平行的最開始的索引 和 最後的索引 
        int h_first_index = 0, h_last_index = matrix.size() - 1;
        //垂直列的最開始的索引 和 最後的索引 
        int v_first_index = 0, v_last_index = matrix[0].size() - 1;
        //數組的長度
        int size = (h_last_index + 1)*(v_last_index + 1);
        //是否遍歷結束
        bool flag = true;
        
        while(flag){
            // 先算開始第一行
            for(int i = v_first_index;i <= v_last_index;i++) {
                list.push_back(matrix[h_first_index][i]);
                if(list.size() >= size){
                    flag = false;
                    break;
                }
            }
            h_first_index ++;
            if(list.size() >= size){
                break;
            }
            // 再算最後一列
            for(int i=h_first_index;i<=h_last_index;i++) {
                list.push_back(matrix[i][v_last_index]);
                if(list.size() >= size){
                    flag = false;
                    break;
                }
            }
            v_last_index --;
            if(list.size()>=size){
                break;
            }
            // 再算最後一行
            for(int i=v_last_index;i>=v_first_index;i--) {
                list.push_back(matrix[h_last_index][i]);
                if(list.size() >= size){
                    flag = false;
                    break;
                }
            }
            h_last_index --;
            if(list.size()>=size){
                break;
            }
            // 最後算開始第一列
            for(int i = h_last_index;i >= h_first_index;i--) {
                list.push_back(matrix[i][v_first_index]);
                if(list.size() >= size){
                    flag = false;
                    break;
                }
            }
            v_first_index ++;
            if(list.size() >= size){
                break;
            }
        }
        return list;
    }
};

另外,我還寫了一個遞歸的版本可以用一個bool數組來判斷是否遍歷,這個消耗一點空間,但是代碼看起來很清晰,代碼:

int di[4][2] = {{0,1},{1,0},{0,-1},{-1,0}};
vector<int> res;
vector<vector<bool>> used;
bool isArea(int x, int y, int row, int col){
    return row>=0 && row<x && col>=0 && col<y;
}
void dfs(int d, const vector<vector<int> > &matrix, int x, int y, int row, int col){
    
    int dx = di[d%4][0], dy = di[d%4][1];
    if(isArea(x,y,row,col) && !used[row][col]){
        int tempRow = row, tempCol = col;
        row += dx, col += dy;
        if(!isArea(x,y,row,col) || used[row][col] ){
            if(res.size() + 1 == x * y){//只有最後一個元素了,直接添加並返回
                res.push_back(matrix[tempRow][tempCol]);
                return;
            }
            dfs(d + 1, matrix, x, y, row - dx, col - dy);
        }else{
            cout<<matrix[tempRow][tempCol]<<endl;
            res.push_back(matrix[tempRow][tempCol]);
            used[tempRow][tempCol] = true;
            dfs(d, matrix, x, y, row, col); 
        }
    }
    
}
vector<int> printMatrix(vector<vector<int> > &matrix) {
    if(!matrix.size() || !matrix[0].size()) return res;
    int x = matrix.size(),y = matrix[0].size();
    
    used = vector<vector<bool>>(x, vector<bool>(y, false));
    dfs(0, matrix, x, y, 0, 0);
    return res;
}

也可以參考yxc大神的方法。

class Solution {
public:
    vector<int> printMatrix(vector<vector<int>>& matrix) {
        vector<int> res;
        if (matrix.empty()) return res;
        int n = matrix.size(), m = matrix[0].size();
        vector<vector<bool>> st(n, vector<bool>(m, false));
        int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
        int x = 0, y = 0, d = 1;
        for (int k = 0; k < n * m; k ++ )
        {
            res.push_back(matrix[x][y]);
            st[x][y] = true;

            int a = x + dx[d], b = y + dy[d];
            if (a < 0 || a >= n || b < 0 || b >= m || st[a][b])
            {
                d = (d + 1) % 4;
                a = x + dx[d], b = y + dy[d];
            }
            x = a, y = b;
        }
        return res;
    }
};


參考鏈接:https://www.acwing.com/solution/AcWing/content/748/

20 包含min函數的棧

定義棧的數據結構,請在該類型中實現一個能夠得到棧中所含最小元素的min函數(時間複雜度應爲O(1))

class Solution {
public:
    /**
    我們除了維護基本的棧結構之外,還需要維護一個單調棧,來實現返回最小值的操作。
    下面介紹如何維護單調棧:

    當我們向棧中壓入一個數時,如果該數 ≤≤ 單調棧的棧頂元素,則將該數同時壓入單調棧中;否則,不壓入,這是由於棧具有先進後出性質,所以在該數被彈出之前,棧中一直存在一個數比該數小,所以該數一定不會被當做最小數輸出。
    當我們從棧中彈出一個數時,如果該數等於單調棧的棧頂元素,則同時將單調棧的棧頂元素彈出。
    單調棧由於其具有單調性,所以它的棧頂元素,就是當前棧中的最小數。
    
    時間複雜度
    四種操作都只有常數次入棧出棧操作,所以時間複雜度都是 O(1)O(1).
    參考鏈接:https://www.acwing.com/solution/AcWing/content/749/
    */
    stack<int> m;
    stack<int> s;
    void push(int value) {
        s.push(value);
        if(m.empty() || m.top() >= value)
            m.push(value);
    }
    void pop() {
        if(m.top() == s.top()) m.pop();
        s.pop();
    }
    int top() {
        return s.top();
    }
    int min() {
        return m.top();
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章