1. 程式人生 > >c++刷題(3/100)數獨,棧和隊列

c++刷題(3/100)數獨,棧和隊列

彈出 iter char col 編寫 實現 滑動窗口 title 表示

stack的基本操作

? s.size():返回棧中的元素數量
? s.empty():判斷棧是否為空,返回true或false
? s.push(元素):返回對棧頂部“元素”的可變(可修改)引用
? s.pop():刪除棧頂元素,類型為void,但並不返回被刪除的元素

? s.top():返回棧頂,不刪除
? s1==s2:若成立,表明s1中的每個元素都等於s2的對應元素,返回true或是false

題目1:用兩個棧實現隊列

https://www.nowcoder.com/practice/54275ddae22f475981afa2244dd448c6?tpId=13&tqId=11158&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

題目描述

用兩個棧來實現一個隊列,完成隊列的Push和Pop操作。 隊列中的元素為int類型。 思路:比較簡單,兩個棧s1,s2 push的時候就往s1裏push,pop的時候,先把s1中的元素全部push到s2,再pop就是隊列順序。這個題也可以描述為如何讓棧逆序輸出
class Solution
{
public:
    void push(int node) {
        stack1.push(node) ;
    }

    int pop() {
        while(!stack1.empty()){
            stack2.push(stack1.top()) ;
            stack1.pop();
        }
        
int res = stack2.top() ; stack2.pop() ; while(!stack2.empty()){ stack1.push(stack2.top()) ; stack2.pop(); } return res ; } private: stack<int> stack1; stack<int> stack2; };

題目2:滑動窗口最大值

https://www.nowcoder.com/practice/1624bc35a45c42c0bc17d17fa0cba788?tpId=13&tqId=11217&tPage=2&rp=2&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking

題目描述

給定一個數組和滑動窗口的大小,找出所有滑動窗口裏數值的最大值。例如,如果輸入數組{2,3,4,2,6,2,5,1}及滑動窗口的大小3,那麽一共存在6個滑動窗口,他們的最大值分別為{4,4,6,6,6,5}; 針對數組{2,3,4,2,6,2,5,1}的滑動窗口有以下6個: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。 思路:這個題O(n*k)很簡單,但是要O(n)就有說法了,o(n)的方法是雙向隊列 先看我的比較挫的版本,用了兩個隊列:
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        queue<int> q ;
        deque<int> qmin ;
        vector<int> ans ;
        if(nums.size()==0||k==0){
            return ans ;
        }
        for(int i=0;i<k;i++){
            if(qmin.empty()){
                qmin.push_back(nums[i]) ;
            }else{
                while(!qmin.empty()&&qmin.back()<nums[i]) qmin.pop_back();
                qmin.push_back(nums[i]) ;
            }
            q.push(nums[i]) ;
        }
        ans.push_back(qmin.front()) ;
        for(int i=k;i<nums.size();i++){
            if(qmin.front()==q.front()){
                qmin.pop_front() ;
            }
            q.pop() ;
            q.push(nums[i]) ;
            while(!qmin.empty()&&qmin.back()<nums[i]) qmin.pop_back();
            qmin.push_back(nums[i]) ;
            ans.push_back(qmin.front()) ;
        }
        return ans ;
    }
};

再看網上大神的版本:一個雙端隊列,代碼也比我簡潔。。。

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        deque<int> qmin ;
        vector<int> ans ;
        int k = size ;
        if(num.size()==0||size==0){
            return ans ;
        }
        for(int i=0;i<num.size();i++){
        // 每當新數進來時,如果發現隊列頭部的數的下標,是窗口最左邊數的下標,則扔掉
            if(!qmin.empty() && qmin.front() == i - k) qmin.pop_front();
            // 把隊列尾部所有比新數小的都扔掉,保證隊列是降序的
            while(!qmin.empty() && num[qmin.back()] < num[i]) qmin.pop_back() ;
            // 加入新數
            qmin.push_back(i) ;
            // 隊列頭部就是該窗口內第一大的
            if((i + 1) >= (int)k) ans.push_back(num[qmin.front()]);
        }
        return ans ;
    }
};

題目3:數獨

編寫一個程序,通過已填充的空格來解決數獨問題。

一個數獨的解法需遵循如下規則:

  1. 數字 1-9 在每一行只能出現一次。
  2. 數字 1-9 在每一列只能出現一次。
  3. 數字 1-9 在每一個以粗實線分隔的 3x3 宮內只能出現一次。

空白格用 ‘.‘ 表示。

技術分享圖片

一個數獨。

技術分享圖片

答案被標成紅色。

Note:

  • 給定的數獨序列只包含數字 1-9 和字符 ‘.‘
  • 你可以假設給定的數獨只有唯一解。
  • 給定數獨永遠是 9x9 形式的。

思路:搜索的題目,在能填數的位置先填一個數,然後判斷合法性,如果合法就從該狀態下再填下一個數。

本來以為要用A*,結果發現直接搜也沒有超時,還有原題目是void函數,沒有返回真的難受,搜索的題如果遞歸函數沒有返回那怎麽知道找到了沒啊。

最後發現別人強行把示例的函數改成了bool型,然後可以過。

最後復習一下個位數的int-》char就是num+‘0‘,char->int就是str-‘0’

class Solution {
public:

    bool checkIsLeagel(vector<vector<char>>& board,int x,int y){
        for(int i=0;i<9;i++){
            if(i!=x&&board[x][y]==board[i][y]){
                return false ;
            }
            if(i!=y&&board[x][y]==board[x][i]){
                return false ;
            }
        }
        for(int i=3*(x/3);i<3*(x/3+1);i++){
            for(int j=3*(y/3);j<3*(y/3+1);j++){
                if(x!=i&&y!=j&&board[x][y]==board[i][j]){
                    return false ;
                }
            }
        }
        return true ;
    }
    
    bool solveSudoku(vector<vector<char>>& board){
        for(int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]==.){
                    for(int k=1;k<=9;k++){
                        board[i][j] = k + 0 ;
                        if(checkIsLeagel(board,i,j)&&solveSudoku(board)){
                            return true ;
                        }
                        board[i][j] = . ;
                    }
                    return false ;
                }
            }
        }
        return true ;
    }

};

ps:記錄兩個數據結構 小頂堆和大頂堆(優先隊列):
priority_queue<int, vector<int>, less<int>> maxHeap; //存儲小的值,值越大,優先級越高
priority_queue<int, vector<int>, greater<int>> minHeap; //存儲大的值,值越小,優先級越高
  雙向隊列:
  1. deq[ ]:用來訪問雙向隊列中單個的元素。
  2. deq.front():返回第一個元素的引用。
  3. deq.back():返回最後一個元素的引用。
  4. deq.push_front(x):把元素x插入到雙向隊列的頭部。
  5. deq.pop_front():彈出雙向隊列的第一個元素。
  6. deq.push_back(x):把元素x插入到雙向隊列的尾部。
  7. deq.pop_back():彈出雙向隊列的最後一個元素。

  deque的一些特點

  1. 支持隨機訪問,即支持[ ]以及at(),但是性能沒有vector好。
  2. 可以在內部進行插入和刪除操作,但性能不及list。
  3. deque兩端都能夠快速插入和刪除元素,而vector只能在尾端進行。
  4. deque的元素存取和叠代器操作會稍微慢一些,因為deque的內部結構會多一個間接過程。
  5. deque叠代器是特殊的智能指針,而不是一般指針,它需要在不同的區塊之間跳轉。
  6. deque可以包含更多的元素,其max_size可能更大,因為不止使用一塊內存。
  7. deque不支持對容量和內存分配時機的控制。
  8. 在除了首尾兩端的其他地方插入和刪除元素,都將會導致指向deque元素的任何pointers、references、iterators失效。不過,deque的內存重分配優於vector,因為其內部結構顯示不需要復制所有元素。
  9. deque的內存區塊不再被使用時,會被釋放,deque的內存大小是可縮減的。不過,是不是這麽做以及怎麽做由實際操作版本定義。
  10. deque不提供容量操作:capacity()和reverse(),但是vector可以。

c++刷題(3/100)數獨,棧和隊列