1. 程式人生 > >建立連結串列的虛擬頭結點 203 Remove Linked List Element,82,147,148,237

建立連結串列的虛擬頭結點 203 Remove Linked List Element,82,147,148,237

 

該邏輯對於刪除第一個元素不適用。

這樣的程式碼不優美

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        
        
while(head!=NULL && head->val == val){ ListNode* delNode = head; head = delNode ->next; delete delNode; } if(head == NULL) return NULL; ListNode* cur = head; while(cur->next != NULL){
if(cur->next->val == val){ //刪除 ListNode* delNode = cur->next; cur->next = delNode->next; delete delNode; } else cur = cur->next; } return head; } };

 

可以設定一個虛擬的頭結點:

 

 

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        
        ListNode* cur = dummyHead;
        
        while(cur->next != NULL){
            if(cur->next->val == val){
                //刪除
                ListNode* delNode = cur->next;
                cur->next = delNode->next;
                delete delNode;
            }
            else
                cur = cur->next;
        }
        
        ListNode* retNode = dummyHead->next;
        delete dummyHead;
        return retNode;
    }
};

這道題想了好久,原因是要把重複的所有元素都刪除,這裡設立一個duplicate標誌位來記錄當前cur是否與下一個結點重複。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* deleteDuplicates(ListNode* head) {
        ListNode* h = new ListNode(-1);
        h->next = head;
        ListNode* pre = h;
        ListNode* cur = head;
        while(cur!=NULL){
            bool duplicate = false;
            while(cur->next!=NULL && cur->val==cur->next->val){
                ListNode* delNode = cur;
                cur = cur->next;
                delete delNode;
                duplicate = true;
            }
            if(duplicate == false){
                pre = cur;
                cur = cur->next;
            }
            else{
                pre->next = cur->next;
                ListNode* delNode = cur;
                cur = cur->next;
                delete delNode;
            }
        }
        return h->next;
    }
};

歸併兩個有序的連結串列。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* h = new ListNode(-1);
        ListNode* cur = h;
        ListNode* cur1 = l1;
        ListNode* cur2 = l2;
        while(cur1 != NULL && cur2 != NULL){
            if(cur1->val <= cur2->val){
                cur->next = cur1;
                cur1 = cur1->next;
            }
            else{
                cur->next = cur2;
                cur2 = cur2->next;
            }
            cur = cur->next;
        }
        if(cur1 != NULL){
            cur->next = cur1;
            
        }
        if(cur2 != NULL){
            cur->next = cur2;
            
        }
        ListNode* ret = h->next;
        delete h;
        return ret;
    }
};

 

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* p = dummyHead;
        while(p->next && p->next->next){
            ListNode* node1 = p->next;
            ListNode* node2 = node1->next;
            ListNode* next = node2->next;
            
            node2->next = node1;
            node1->next = next;
            p->next = node2;
            
            p = node1;
        }
        ListNode* ret = dummyHead->next;
        delete dummyHead;
        return ret;
    }
};

 

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseKGroup(ListNode* head, int k) {
        if(!head || k==1) return head;
        ListNode* dummy = new ListNode(-1);
        ListNode* pre = dummy, *cur = head;
        dummy->next = head;
        int i = 0;
        while(cur){
            i++;
            if(i%k == 0){
                pre = reverseOneGroup(pre, cur->next);
                cur = pre->next;
            }
            else{
                cur = cur->next;
            }
        }
        return dummy->next;
    }
    
    ListNode* reverseOneGroup(ListNode* pre, ListNode* next){
        ListNode* last = pre->next;
        ListNode* cur = last->next;
        while(cur!=next)
        {
            last->next = cur->next;
            cur->next = pre->next;   //注意這裡是指向pre->next
            pre->next = cur;
            cur = last->next;
        }
        return last;     //返回需要翻轉的最後一個元素
    }
};

用連結串列來實現插入排序。

思路:建立一個輔助的新連結串列,並且使用一個指標遍歷原連結串列,每次將原連結串列中的一個節點插入到新連結串列的合適位置(即該節點的值大於新連結串列上的節點的值,又小於後一節點的值)。最後將新連結串列的頭部返回即可。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* insertionSortList(ListNode* head) {
        
        if(head == NULL || head->next == NULL)
            return head;
        
        ListNode* pre = new ListNode(-1), *ans = pre;   //建立一個新連結串列的頭結點,並用一個臨時變數來儲存
        ListNode* cur = head;  //cur是原連結串列的指標
        while(cur != NULL){
            //每次迴圈前重置pre為頭結點,保證每次都從頭到尾遍歷
            pre = ans;
            while(pre->next != NULL && pre->next->val < cur->val){
                pre = pre->next;
            }
            
            //此時,pre->next->val大於cur->val,應把cur插入到pre後
            //儲存原連結串列當前節點的下一個節點
            ListNode* tmp = cur->next;
            //插入cur到pre後
            cur->next = pre->next;
            pre->next = cur;
            
            cur = tmp; //cur在原連結串列中後移一位
        }
        return ans->next;
    }
};

本題適用於歸併排序,難點是:怎麼樣找到分治時的middle指標,採用快慢指標的思想。快指標一次走兩步,慢指標一次走一步,當快指標走到頭時,慢指標剛好走到中間位置,此位置即為middle的位置。

快慢指標思想:

 快慢指標是指指標移動的步長,快指標移動的快,慢指標移動的慢,例如可以讓快指標一次移動兩個步長,讓慢指標一次移動一個步長。

快慢指標有兩個比較重要的應用:

1、判斷連結串列是否為單鏈表

2、在有序連結串列中尋找中位數

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        //將一個連結串列平分為兩個連結串列
        if(!head || !head->next) return head;
        ListNode* slow = head, *fast = head, *pre = head;
        while(fast && fast->next){
            pre = slow;
            slow = slow->next;
            fast = fast->next->next;
        }
        pre->next = NULL;
        return merge(sortList(head), sortList(slow));
    }
    
    ListNode* merge(ListNode* l1, ListNode* l2){
        ListNode* dummy = new ListNode(-1);
        ListNode* cur = dummy;
        while(l1 && l2){
            if(l1->val < l2->val){
                cur->next = l1;
                l1 = l1->next;
            }
            else{
                cur->next = l2;
                l2 = l2->next;
            }
            cur = cur->next;
        }
        if(l1) cur->next = l1;
        if(l2) cur->next = l2;
        return dummy->next;
    }
};

改變節點的值來解決問題。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        if(node == NULL)
            return;
        if(node->next == NULL){
            delete node;
            node = NULL;
            return;
        }
        node->val = node->next->val;
        ListNode* delNode = node->next;
        node->next = delNode->next;
        delete delNode;
        return;
    }
};