zoukankan      html  css  js  c++  java
  • 建立链表的虚拟头结点 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;
        }
    };

    又重新做了一遍这道题,思路和前面设置标志位记录重复的不太一样。重点在于在两个结点不相同时,需要判断在它们前面是否存在重复的元素,若存在,pre需要跳过这些结点;若不存在,pre直接指向pre->next即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) {
            if(head == NULL)
                return NULL;
            ListNode dummy(0);
            dummy.next = head;
            ListNode* pre = &dummy, *cur = head;
            while(cur){
                ListNode* next = cur->next;
                while(next && next->val == cur->val){
                        cur = cur->next;
                        next = next->next;
                    }
                if(cur != pre->next){
                    cur = next;   //将最后一个重复的跳过
                    pre->next = cur;
                }
                else{  //pre和cur之间没有重复的
                    pre = cur;
                    cur = next;
                }
                    
            }
            return dummy.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;
        }
    };

    一样的思路,又写了一遍,创建一个新链表,dummy指向新链表的头结点。扫描原链表,对于每个结点v,从前往后扫描已排序好的结果链表,找到第一个比v大的u结点,将v插入到u之前。

    时间复杂度:共遍历n个结点,为每个结点找到合适的位置,最多再遍历n次,所以总的时间复杂度是O(n^2)

    /**
     * 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) {
            ListNode *dummy = new ListNode(-1);   //dummy指向已排序链表的头结点
            
            while(head){
                ListNode* next = head->next;
                ListNode *p = dummy;
                while(p->next && p->next->val <= head->val)
                    p = p -> next;  //p->next指向比head大的第一个结点,则p指向比head小的最后一个结点
                //将head插入到p和p->next之间
                head->next = p->next;
                p->next = head;
                
                head = next;
            }
            return dummy->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;
        }
    };
  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/Bella2017/p/10176600.html
Copyright © 2011-2022 走看看