5.2打卡:劍指 offer兩題:用兩個棧實現隊列/旋轉數組最小數字

用兩個棧實現隊列

題目描述

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

思路:

1、當插入時,直接插入 stack1

2、當彈出時,當 stack2 不爲空,彈出 stack2 棧頂元素,如果 stack2 爲空,將 stack1 中的全部數逐個出棧入棧 stack2,再彈出 stack2 棧頂元素

class Solution
{
public:
    void push(int node) {
        stack1.push(node);
    }

    int pop() {
        //當彈出時,當 stack2 不爲空,彈出 stack2 棧頂元素,
        //如果 stack2 爲空,將 stack1 中的全部數逐個出棧入棧 stack2,
        //再彈出 stack2 棧頂元素
        if(stack2.empty())
        {
            while(!stack1.empty())
            {
                stack2.push(stack1.top());
                stack1.pop();
            }
        }
        int ret = stack2.top();
        stack2.pop();
        return ret;
        
    }

private:
    stack<int> stack1;
    stack<int> stack2;
};

注意:這裏實際上我自己忘了C++ stack/vector/deque的一些操作,所以這裏在記錄一下鞏固一下。

棧(stack)

//頭文件
#include<stack>
//常用方法
empty() //堆棧爲空則返回真
pop() //移除棧頂元素
push() //在棧頂增加元素
size() //返回棧中元素數目
top() //返回棧頂元素

隊列(queue)

//頭文件
#include<queue>
//常用方法
empty() 判斷隊列是否爲空,返回類型爲bool
size() 返回隊列中元素的個數
front() 返回隊列隊首元素
back() 返回隊列隊尾元素
push(ele) 將元素ele插入到隊尾
pop 隊首元素出隊

向量(vector)

#include<vector>//頭文件
//常用方法
c.clear() 移除容器中所有數據。
c.empty() 判斷容器是否爲空。
c.erase(pos) 刪除pos位置的數據
c.erase(beg,end) 刪除[beg,end)區間的數據
c.front() 傳回第一個數據。
c.insert(pos,elem) 在pos位置插入一個elem拷貝
c.pop_back() 刪除最後一個數據。
c.push_back(elem) 在尾部加入一個數據。
c.resize(num) 重新設置該容器的大小
c.size() 回容器中實際數據的個數。
c.begin() 返回指向容器第一個元素的迭代器
c.end() 返回指向容器最後一個元素的迭代器

旋轉數組最小數字

題目描述

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

思路(二分查找思想):

參考:https://www.nowcoder.com/questionTerminal/9f3231a991af4f55b95579b44b7a01ba?answerType=1&f=discussion
二分查找的 mid 如果落在左半邊,那麼就 lo=mid+1,如果落在右半邊,就減小 hi=mid。不斷縮小範圍,最終,lo 一定會掉到最低點。是要如何判斷 mid 落在那一邊呢。因爲左半邊 >= 右半邊,如果原數組是嚴格遞增的,你可以說,當 a[mid] > a[0] 那就是左半邊。但是考慮下面這幅圖:

如果原數組只有開始部分遞增,之後很長一段都是平坦的,那麼旋轉後可能是上圖的樣子。a[mid] == a[lo] == a[hi],根本沒法判斷 mid 在那邊。解決的方法很簡單:

while(a[lo] == a[hi]){
    ++lo;
    --hi;
}

這樣操作以後,一定有 a[lo] > a[hi],一旦 lo 掉到了最低點,這個條件就不成立了。判斷 mid 在左在右也很簡單了,如果 a[mid] >= a[lo] 那就是左邊。如果 a[mid] <= a[hi] 那就是右邊。

如果在左邊,那就 lo=mid+1,這樣把 lo 向右邊推進。如果在右邊,爲了避免 hi 爬到了左邊去 hi=mid 即可。最終終止條件,就是 lo 落到了最低點。

class Solution {
public:
    int minNumberInRotateArray(vector<int> a) {
        if(a.size() == 0) return 0;
        int lo = 0, hi = a.size() - 1;
        //防止原數組只有開始部分遞增,之後很長一段都是平坦的
        while(a[lo] == a[hi])
        {
            ++ lo;
            -- hi;
        }
        /*
        if (a.size() == 0) return 0;
        int lo = 0, hi = a.size()-1;
        while(a[lo] == a[hi]){
            ++lo;
            --hi;
        }*/
        while(a[lo] > a[hi]){
            int mid = lo + (hi-lo) / 2;

            if(a[mid] >= a[lo]){
                lo = mid + 1;
            }else if(a[mid] <= a[hi]){
                hi = mid;
            }
        }
        return a[lo];
    }
};

 

 

 

 

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