LeetCode刷題之隊列

641. 設計循環雙端隊列

設計實現雙端隊列。
你的實現需要支持以下操作:
MyCircularDeque(k):構造函數,雙端隊列的大小爲k。 insertFront():將一個元素添加到雙端隊列頭部。
如果操作成功返回 true。 insertLast():將一個元素添加到雙端隊列尾部。如果操作成功返回 true。
deleteFront():從雙端隊列頭部刪除一個元素。 如果操作成功返回 true。
deleteLast():從雙端隊列尾部刪除一個元素。如果操作成功返回 true。
getFront():從雙端隊列頭部獲得一個元素。如果雙端隊列爲空,返回 -1。 getRear():獲得雙端隊列的最後一個元素。
如果雙端隊列爲空,返回 -1。 isEmpty():檢查雙端隊列是否爲空。 isFull():檢查雙端隊列是否滿了。 示例:

MyCircularDeque circularDeque = new MycircularDeque(3); // 設置容量大小爲3
circularDeque.insertLast(1); // 返回 true
circularDeque.insertLast(2); // 返回 true
circularDeque.insertFront(3); // 返回 true
circularDeque.insertFront(4); // 已經滿了,返回 false
circularDeque.getRear(); // 返回 2 circularDeque.isFull();
// 返回 true circularDeque.deleteLast(); // 返回 true
circularDeque.insertFront(4); // 返回 true
circularDeque.getFront(); // 返回 4

提示:

所有值的範圍爲 [1, 1000] 操作次數的範圍爲 [1, 1000] 請不要使用內置的雙端隊列庫。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/design-circular-deque
難度:中等
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。


思路:這個設計題目一開始讓我有點摸不着頭腦,第一次接觸所謂雙端隊列。但是我在題解去,看一個高贊回答的dalao解釋後明白了所謂循環雙端隊列是什麼玩意。
總結起來就一句話:隊列中,rear和front職責分明,分別負責一頭一尾(即分別管理進出),但是在雙端隊列中rear和front的職責共享。重要的是這告訴我們可以基於隊列的條件去設置循環雙端隊列,我只需要對front和rear的操作共享化(即兩者都可以管理進出)。那麼隊空隊滿的條件判斷都可以基於隊列來設計。
好了下面是順序存儲結構的實現,有時間再發給鏈式存儲結構的實現。
最後不得不感嘆一句,LeetCode上C++簡直優勢佔盡,幾乎優質題解都是C++。

typedef struct MyCircularDeque 
{
    int front;
    int rear;
    int MAXSIZE;
    int data[];     //這是伸縮型數組成員,可以理解爲動態數組,大小依據內存分配而定。不明白自行查閱
} MyCircularDeque;


bool myCircularDequeIsEmpty(MyCircularDeque* obj);
bool myCircularDequeIsFull(MyCircularDeque* obj);


/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque* myCircularDequeCreate(int k) {
    MyCircularDeque* obj = (MyCircularDeque*)malloc(sizeof(MyCircularDeque) + (k + 1) * sizeof(int));
    if(!obj)
        return NULL;
    memset(obj, 0, sizeof(MyCircularDeque) + (k + 1) * sizeof(int));
    obj->MAXSIZE = k + 1;	//多分配了一個位置是爲了方便隊滿隊空的判斷.

    return obj;
}

/** Adds an item at the front of Deque. Return true if the operation is successful. */
bool myCircularDequeInsertFront(MyCircularDeque* obj, int value) {
    if(myCircularDequeIsFull(obj))
        return false;

    obj->front = (obj->front - 1 + obj->MAXSIZE) % obj->MAXSIZE;
    obj->data[obj->front] = value;
    return true;
}

/** Adds an item at the rear of Deque. Return true if the operation is successful. */
bool myCircularDequeInsertLast(MyCircularDeque* obj, int value) {
    if(myCircularDequeIsFull(obj))
        return false;

    obj->data[obj->rear] = value;
    obj->rear = (obj->rear + 1) % obj->MAXSIZE;
    return true;
}

/** Deletes an item from the front of Deque. Return true if the operation is successful. */
bool myCircularDequeDeleteFront(MyCircularDeque* obj) {
    if(myCircularDequeIsEmpty(obj))
        return false;
    
    obj->front = (obj->front + 1) % obj->MAXSIZE;
    return true;
}

/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
bool myCircularDequeDeleteLast(MyCircularDeque* obj) {  //OVER
    if(myCircularDequeIsEmpty(obj))
        return false;

     obj->rear = (obj->rear - 1 + obj->MAXSIZE) % obj->MAXSIZE;
     return true;
}

/** Get the front item from the deque. */
int myCircularDequeGetFront(MyCircularDeque* obj) { //OVER
    return myCircularDequeIsEmpty(obj) ? -1 : obj->data[obj->front];
}

/** Get the last item from the deque. */
int myCircularDequeGetRear(MyCircularDeque* obj) {  //OVER
    if(myCircularDequeIsEmpty(obj))
        return -1;

    int index = (obj->rear - 1 +obj->MAXSIZE) % obj->MAXSIZE;
    return obj->data[index];
}

/** Checks whether the circular deque is empty or not. */
bool myCircularDequeIsEmpty(MyCircularDeque* obj) { //OVER
    return obj->rear == obj->front ? true : false;
}

/** Checks whether the circular deque is full or not. */
bool myCircularDequeIsFull(MyCircularDeque* obj) {  //OVER
    return (obj->rear +1) % obj->MAXSIZE == obj->front ? true : false;
}

void myCircularDequeFree(MyCircularDeque* obj) {    //OVER
    free(obj);
    obj = NULL;
}

622. 設計循環隊列

設計實現雙端隊列。 你的實現需要支持以下操作:

MyCircularDeque(k):構造函數,雙端隊列的大小爲k。 insertFront():將一個元素添加到雙端隊列頭部。
如果操作成功返回 true。 insertLast():將一個元素添加到雙端隊列尾部。如果操作成功返回 true。
deleteFront():從雙端隊列頭部刪除一個元素。 如果操作成功返回 true。
deleteLast():從雙端隊列尾部刪除一個元素。如果操作成功返回 true。
getFront():從雙端隊列頭部獲得一個元素。如果雙端隊列爲空,返回 -1。 getRear():獲得雙端隊列的最後一個元素。
如果雙端隊列爲空,返回 -1。 isEmpty():檢查雙端隊列是否爲空。 isFull():檢查雙端隊列是否滿了。 示例:

MyCircularDeque circularDeque = new MycircularDeque(3); // 設置容量大小爲3
circularDeque.insertLast(1); // 返回 true
circularDeque.insertLast(2); // 返回 true
circularDeque.insertFront(3); // 返回 true
circularDeque.insertFront(4); // 已經滿了,返回 false
circularDeque.getRear(); // 返回 2 circularDeque.isFull();
// 返回 true circularDeque.deleteLast(); // 返回 true
circularDeque.insertFront(4); // 返回 true
circularDeque.getFront(); // 返回 4

提示:

所有值的範圍爲 [1, 1000] 操作次數的範圍爲 [1, 1000] 請不要使用內置的雙端隊列庫。

來源:力扣(LeetCode)
難度:中等
鏈接:https://leetcode-cn.com/problems/design-circular-deque
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

思路:沒什麼好說的。。。

typedef struct MyCircularDeque 
{
    int front;
    int rear;
    int MAXSIZE;
    int data[];     //這是伸縮型數組成員,可以理解爲動態數組,大小依據內存分配而定。不明白自行查閱
} MyCircularDeque;


bool myCircularDequeIsEmpty(MyCircularDeque* obj);
bool myCircularDequeIsFull(MyCircularDeque* obj);


/** Initialize your data structure here. Set the size of the deque to be k. */
MyCircularDeque* myCircularDequeCreate(int k) {
    MyCircularDeque* obj = (MyCircularDeque*)malloc(sizeof(MyCircularDeque) + (k + 1) * sizeof(int));
    if(!obj)
        return NULL;
    memset(obj, 0, sizeof(MyCircularDeque) + (k + 1) * sizeof(int));
    obj->MAXSIZE = k + 1;

    return obj;
}

/** Adds an item at the front of Deque. Return true if the operation is successful. */
bool myCircularDequeInsertFront(MyCircularDeque* obj, int value) {
    if(myCircularDequeIsFull(obj))
        return false;

    obj->front = (obj->front - 1 + obj->MAXSIZE) % obj->MAXSIZE;
    obj->data[obj->front] = value;
    return true;
}

/** Adds an item at the rear of Deque. Return true if the operation is successful. */
bool myCircularDequeInsertLast(MyCircularDeque* obj, int value) {
    if(myCircularDequeIsFull(obj))
        return false;

    obj->data[obj->rear] = value;
    obj->rear = (obj->rear + 1) % obj->MAXSIZE;
    return true;
}

/** Deletes an item from the front of Deque. Return true if the operation is successful. */
bool myCircularDequeDeleteFront(MyCircularDeque* obj) {
    if(myCircularDequeIsEmpty(obj))
        return false;
    
    obj->front = (obj->front + 1) % obj->MAXSIZE;
    return true;
}

/** Deletes an item from the rear of Deque. Return true if the operation is successful. */
bool myCircularDequeDeleteLast(MyCircularDeque* obj) {  //OVER
    if(myCircularDequeIsEmpty(obj))
        return false;

     obj->rear = (obj->rear - 1 + obj->MAXSIZE) % obj->MAXSIZE;
     return true;
}

/** Get the front item from the deque. */
int myCircularDequeGetFront(MyCircularDeque* obj) { //OVER
    return myCircularDequeIsEmpty(obj) ? -1 : obj->data[obj->front];
}

/** Get the last item from the deque. */
int myCircularDequeGetRear(MyCircularDeque* obj) {  //OVER
    if(myCircularDequeIsEmpty(obj))
        return -1;

    int index = (obj->rear - 1 +obj->MAXSIZE) % obj->MAXSIZE;
    return obj->data[index];
}

/** Checks whether the circular deque is empty or not. */
bool myCircularDequeIsEmpty(MyCircularDeque* obj) { //OVER
    return obj->rear == obj->front ? true : false;
}

/** Checks whether the circular deque is full or not. */
bool myCircularDequeIsFull(MyCircularDeque* obj) {  //OVER
    return (obj->rear +1) % obj->MAXSIZE == obj->front ? true : false;
}

void myCircularDequeFree(MyCircularDeque* obj) {    //OVER
    free(obj);
    obj = NULL;
}

總結對於這種隊列的設計,主要考慮的是什麼情況隊空、什麼情況隊滿,還有清楚隊空和隊滿時,rear和front指針的位置如何。如果考慮到以上這些條件,相信設計一個隊列不難。

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