zoukankan      html  css  js  c++  java
  • 链表_数据结构

    Linked List

    目录

    • [环形链表知识点补充2019.2.25](#circle linklist)
    • [000.链表数据结构的实现](#linklist implement)
    • [876.链表的中点问题](#876.Middle of the Linked List)
    • [2.两个链表的反向数学相加](#2.Add Two Numbers)
    • [445.两个链表数学相加](#445.Add Two Numbers II)
    • [24.交换链表相邻的点](#24.Swap Nodes in Pairs)
    • [83.删除有序列表中的重复点](#83.remove the duplication in sorted linked-list)
    • [86.分离数组](#86.partition list)
    • [203.链表结点的删除](#203.Remove Linked List Elements)
    • [328.奇偶链表](#328.Odd Even Linked List)
    • [817.链表中元素的分部](#817.Linked List Components)
    • [23.合并k个有序链表](#23.Merge k Sorted Lists)
    • [725.将链表按要求进行分块](#725.Split Linked List in Parts)
    • [148.链表排序,这道题很重要](#148.Sort List)
    • [430.多维度的双向链表变成一维度的双向链表](#430.Flatten a multilevel Doubly Linked List)
    • [109.将有序链表转换成平衡二叉查找树](#109.convert the sort list to heigh balanced BST)
    • [25.一次反转k个链表](#25.reverse linklist node in k-group)

    环形链表实现

    // 使用环形链表的数据结构来实现
    // 首尾结点的链接很机智,可以学习
    #include <list>
    #include <iostream>
    
    int lastRemaining(unsigned int n,unsigned int m)
    {
    	if(n<1 || m<1)
    		return -1;
    
    	unsigned int i=0;
    	list<int> numbers;
    	for(int i=0;i<n;++i)             // construct the circle list
    		numbers.push_back(i);
    
    	list<int>::iterator current=numbers.begin();
    	while(numbers.size()>1){
    		for(int i=1;i<m;++i){
    			current++;
    			if(current==numbers.end())     // implement the circle list  end concat the begin
    				current=numbers.begin() 
    		}
    		list<int>::iterator next=++current;
    		if(next==numbers.end())
    			next=numbers.begin();
    		--current;
    		numbers.erase(current);
    		current=next;                     // next instead of the start counting point
    	}
    	return *(current);                    // get iterator elements,directed use reference
    }
    
    

    在写数据结构代码是犯了一个非常低级的错误,就是没能在循环中和列表中index 的相对应的关系,区分我们口中的“第几个”。
    千万不要尝试去排序链表
    链表在寻找其中的元素时要重开始的指针开始进行。

    linklist new =l->next; //新建指针new 指向链表l的第一个结点
    linklist new=*l  //相当于新建一个指针new 指向链表头结点。
    

    头结点,这是一个很重要的知识点。
    头结点中包含头指针
    头结点放在第一个元素结点之前
    头结点是为了操作的方便统一,有了这个头结点对元素的插入和删除就可以和其他元素相同处理

    还有一个注意点就是,链表的查找是从第一个结点开始的,不是头结点

    链表数据结构的实现

    链表数据结构的实现:

    1. linklist.h 头文件(linklist.hpp)

    2. linklist.cpp 实现

    3. main.cpp 测试实现

    • 头文件的实现
    #ifndef LinkList_hpp
    #define LinkList_hpp
    #include<stdio.h>
    typedef struct node{
               int data;
               struct node *next;
    }NODE;
    
    class LinkList{
    private:
          NODE *head;
    public:
        LinkList() {head=NULL;}
        ~LinkList();
        bool clearSqList();
        bool isEmpty() {return head=NULL;}
        int Length();
        bool GetElem(int i,int *e);
        int localElem(int e);
        bool PriorElem(int cur_e, int *pre_e);
        bool NextElem(int cur_e, int *next_e);
        bool Insert(int i, int e);
        bool Delete(int i, int *e);
        NODE * Reverse();
    };
    #endif /* LinkList_hpp */
    
    
    • 具体实现的实现 linklist.cpp
    //  LinkList.cpp
    //  DataStructure
    //
    //  Created by 邓烁邓烁 on 2018/9/30.
    //  Copyright © 2018年 邓烁. All rights reserved.
    //
    
    
    // implement the operation
    #include "LinkList.hpp"
    #include<iostream>
    
    LinkList::~LinkList(){
        NODE *p=head;
        while(head){
            p=head;
            head=head->next;
            delete(p);
        }
        
    }
    
    bool LinkList::clearSqList(){
        NODE *p=head;
        while(head){
            p=head;
            head=head->next;
            delete(p);
        }
        return true;
    }
    
    int LinkList::Length(){
        NODE*p=head;
        int j=0;
        while(p){
            j++;
            p=p->next;
        }
        return j;
    }
    
    /*
     need the return value   ,define a void function
     */
    bool LinkList::GetElem(int i, int *e){
        NODE *p=head;
        p=head;
        int j=0;
        while(p &&j<i){
            p=p->next;
            j++;
        }
        if(!p)
            return false;
        *e=p->data;
        return true;
    }
    int LinkList::localElem(int e){
        NODE *p=head;
        p=head;
        int index=0;
        while(p){
            if(p->data==e)
                return index;
            else  p=p->next;
            index ++;
            
        }
        std::cout<<"元素不存在列表中"<< std::endl;
        exit(1);
    }
    
    bool LinkList::PriorElem(int cur_e, int *pre_e)
    {
        NODE *p = head;
        if (p->data == cur_e) return false;//是头结点,不存在上一个元素
        while (p->next != NULL)
        {
            if (p->next->data == cur_e)
            {
                *pre_e = p->data;
                return true;
            }
            else
                p = p->next;
        }
        return false;//遍历完不存在或者只有一个头结点
        
    }
    bool LinkList::NextElem(int cur_e, int *next_e)
    {
        NODE *p = head;
        if (head == NULL || head->next == NULL) return false;
        while (p->next != NULL)
        {
            if (p->data == cur_e)
            {
                *next_e = p->next->data;
                return true;
            }
            else
                p = p->next;
        }
        return false;
    }
    /*
     insert elements in position e
     */
    bool LinkList::Insert(int i, int e)
    {
        NODE *p = head,*s;
        int j = 0;
        if (i == 0)
        {
            s = (NODE *)new NODE[1];  //new a node from the memory
            s->data = e;
            s->next = p;
            head = s;
            return true;
        }
        while (p&&j < i - 1)
        {
            p = p->next;
            j++;
        }
        if (p == NULL)
            return false;//到队尾了
        s= (NODE *)new NODE[1];
        // this three statement is core code
        s->data = e;
        s->next = p->next;
        p->next = s;
        return true;
    }
    
    bool LinkList::Delete(int i, int *e)
    {
        NODE *p = head, *s;
        if (p == NULL) return false;
        int j = 0;
        if (i == 0)
        {
            head = head->next;
            *e = p->data;
            delete p;
            p = NULL;
            return true;
        }
        while (p&&j < i - 1)
        {
            j++;
            p = p->next;
        }
        if (p == NULL)
            return false;
        s = p->next;
        p->next = p->next->next;
        *e = s->data;
        delete s;  // it's mean free s from memory
        s = NULL;
        return true;
    }
    NODE* LinkList::Reverse()
    {
        if (head == NULL || head->next == NULL) return head;
        NODE *p = head,*q=head->next,*r;
        head->next = NULL;
        while (q)
        {
            r = q->next;
            q->next = p;
            p = q;
            q = r;
        }
        head = p;
        return head;
    }
    
    • 编写用例代码来实现 main.cpp
    //  main.cpp
    //  DataStructure
    //
    //  Created by 邓烁邓烁 on 2018/9/30.
    //  Copyright © 2018年 邓烁. All rights reserved.
    //
    // 编写测试用例来检测代码的正确性
    #include <iostream>
    #include"LinkList.hpp"
    using namespace std;
    int main()
    {
        int a = 0;
        int *p = &a;
        LinkList li;
        li.Insert(0, 5);
        li.Insert(1, 4);
        li.Insert(2, 12);
        li.Insert(3, 5);
        li.Insert(3, 6);
        li.Insert(1, 7);
        cout <<"链表长度"<< li.Length()<<endl;
        cout << "各个元素的值是:";
        for (int i = 0;i < li.Length();i++)//遍历该链表
        {
            
            if (li.GetElem(i, p))
                cout << *p<<"   ";
        }
        cout << endl;
        cout << "反转后各个元素的值是:";
        NODE* re_li=li.Reverse();
        while (re_li)
        {
            cout << re_li->data << "   ";
            re_li = re_li->next;
        }
        cout << endl;
    }
    

    链表中结点

    • 未实现版本,要再考虑一下
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* middleNode(ListNode* head) {
            vector<int> list_array;
            int num=0;
            while(head!=NULL){
                head=head->next;
                num++;
            }
            int middle=num/2;
            int j=0;
            while(head!=NULL && j<middle){
                head=head->next;
                j++;
            }
            return head;
            
        }
    };
    
    • 双指针版本 AC
    lass Solution {
    public:
        ListNode* middleNode(ListNode* head) {
            struct ListNode *start=head;
            struct ListNode *end=head;
            if(head==NULL){
                return head;
            }else if(!start->next){ //only one node 
                return start;
            }else if(!end->next->next){ //only two node 
                return start->next;
            }
            while(start!=NULL && end!=NULL && end->next!=NULL){
                start=start->next;
                end=end->next->next;
                if(!end->next){
                    return start;
                }
                if(start->next && !end->next->next){
                    return start->next;
                }
            }
            return start; // 我认为这一句完全不用加
        }
    };
    

    2.Add Two Numbers

    两个链表的反向数学运算

    // 解法缺少一个0 结点
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            stack<int> s1;
            stack<int> s2;
            ListNode *helper=new ListNode(0);
            ListNode *cur=helper;
            cur->next=NULL;
            while(l1){
                s1.push(l1->val);
                l1=l1->next;
            }
            while(l2){
                s2.push(l2->val);
                l2=l2->next;
            }
            int flag=0;
            while(!s1.empty() || !s2.empty()){
                int num_l1=0;
                if(!s1.empty()){
                    num_l1=s1.top();
                    s1.pop();
                    }
                int num_l2=0;
                if(!s2.empty()){
                    num_l2=s2.top();
                    s2.pop();
                }
                ListNode *temp=new ListNode((num_l1+num_l2+flag)%10);
                cur->next=temp;
                cur=temp;
                flag=num_l1+num_l2+flag>=10;
            }
            return helper;
            
        }
    };
    

    另外一种直接进行链表的直接推进

    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            // 题意可以认为是实现高精度加法
            ListNode *head = new ListNode(0);
            ListNode *ptr = head;
            int carry = 0;
            while (true) {
                if (l1 != NULL) {
                    carry += l1->val;
                    l1 = l1->next;
                }
                if (l2 != NULL) {
                    carry += l2->val;
                    l2 = l2->next;
                }
                ptr->val = carry % 10;
                carry /= 10;
                // 当两个表非空或者仍有进位时需要继续运算,否则退出循环
                if (l1 != NULL || l2 != NULL || carry != 0) {
                    ptr = (ptr->next = new ListNode(0));
                } else break;
            }
            return head;
        }
    };
    

    两个链表的数学运算

    445.Add Two Numbers II

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            int num1=list2number(l1);
            int num2=list2number(l2);
            struct ListNode list_node;
            list_node=number2list(num1+num2);
            return list_node;
            
        }
        
        int list2number(ListNode *head){
            if(head==NULL) return 0;
            int value=0;
            while(!head){
                value=10*value;
                value+=head->val;
                head=head->next;
            }
            return value;
        }
        # 添加头结点的思路是对的
        # 但是好像就是链表的初始化有点问题
        ListNode* number2list(int num){
            struct ListNode num_list;
            int num_node;
            while(num>0){
                num_node=num%10;
                num=int(num/10);
                struct ListNode head;
                head->val=num_node;
                head->next=num_list;
                num_list=head;
            }
            return num_list;
    
        }
    };
    

    copy from other author

    • 主要是利用两个栈来实现,和进制进1时如何处理。
    class Solution {
    public:
        ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
            stack<int> s1;
            stack<int> s2;
            while(l1){
                s1.push(l1->val);
                l1=l1->next;
            }
            while(l2){
                s2.push(l2->val);
                l2=l2->next;
            }
            ListNode* cur=NULL;
            int c=0;               //define a flag ,if value big than 10 
            while(!s1.empty() || !s2.empty()){
                int value1=0;
                if(!s1.empty()){
                    value1=s1.top();
                    s1.pop();
                }
                int value2=0;
                if(!s2.empty()){
                    value2=s2.top();
                    s2.pop();
                }
                ListNode* temp=new ListNode((value1+value2+c)%10);
                temp->next=cur;
                cur=temp;
                c=(value1+value2+c)>=10;     // a true or false statement
            }
            if(c==1){
                ListNode*temp=new ListNode(1);
                temp->next=cur;
                cur=temp;
            }
            return cur;
    
        }
    };
    

    24.Swap Nodes in Pairs

    链表相邻结点的交换

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    # 我自己的思路实现判定结点是否存在,直接在原地进行指针的交换,实现元素顺序的交换,在编程实现中成功的将自己给绕晕
    
    # 下面解题方法的重点和启发点在于/;新建了一个辅助用的头结点来进行添加操作  new listnode (0);这在交换过程中非常有用,直接利用next指针进行添加元素即可。
    class Solution {
    public:
        ListNode* swapPairs(ListNode* head) {
            if(head==NULL || head->next==NULL){
                return head;
            }
            ListNode *ret=head;
            ListNode *helper=new ListNode(0);
            ListNode *cur=helper;
            while(ret && ret->next){
                ListNode *next=ret->next->next;
                cur->next=ret->next;
                cur=cur->next;
                cur->next=ret;
                cur=cur->next;
                cur->next=NULL;
                ret=next;
            }
            if(ret) cur->next=ret;  # 单剩一个结点时  !ret->next  添加最后一个结点
            return helper->next;
            
        }
    };
    

    83.remove the duplication in sorted linked-list

    // 这里面又一个非常重要的知识点就是
    // 链表进行修改的时候,要把头结点进行备份复制
    // 对 复制的结点进行修改操作,最后直接返回头结点就可以
    class Solution {
    public:
        ListNode* deleteDuplicates(ListNode* head) {
            if(head==NULL|| head->next==NULL)
                return head;
            ListNode *temp=head;
            while(temp->next){
                if((temp->next)->val==temp->val)
                {
                    ListNode *delNode=temp->next;
                    temp->next=temp->next->next;
                    delete(delNode);                        //内存结点的释放
                    //temp=prev->next;
                }
                else{
                    temp=temp->next;
                }
            }    
            return head;
        }
    };
    
    // 较慢的版本,可能是 且语句
    class Solution {
    public:
        ListNode* deleteDuplicates(ListNode* head) {
            ListNode* cur = head;
            while (cur) {
                while (cur->next && cur->val == cur->next->val)
                    cur->next = cur->next->next;
                cur = cur->next;
            }
            return head;
        }
    };
    // 这个是删除重复点(两个结点都删除),比较鲁棒的代码
    
    struct ListNode
    {
        int val;
        ListNode next;
    };
    void DeleteDuplication(ListNode **PHead){
        if(PHead==nullptr || *PHead==nullptr)
            return;
        ListNode *preNode=nullptr;
        ListNode *pNode=*PHead;
        while(pNode !=nullptr){
            ListNode *pNext=pNode->next;
            bool NeedDelete=false;
            if(pNext!=nullptr && pNext->val==pNode->val)
                NeedDelete=true;
            if(!NeedDelete){
                preNode=pNode;   // 保留要删除结点的前一个结点
                pNode=pNode->next;
            }
            // 需要删除
            else{
                int value=pNode->val;
                ListNode *nodeToBeDel=pNode;
                while(nodeToBeDel!=nullptr && nodeToBeDel->val==value){
                    pNext=nodeToBeDel->next;
                    delete nodeToBeDel;
                    nodeToBeDel=nullptr;
                    nodeToBeDel=pNext;     // 删除第二个结点
                }
                if(preNode==nullptr)
                    *PHead=pNext;
                else
                    preNode->next=pNext;
                pNode=pNext;
    
            }
        }
    }
    
    

    86.partition list

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    // 这个版本的结果是运行时间超过了限制
    // time limited exceed
    // 都是一些基础问题,空结点如何定义
    // 怎么实现链表之间的链接
    class Solution {
    public:
        ListNode* partition(ListNode* head, int x) {
            ListNode *cur=head;
            ListNode *tmp1=head;
            ListNode *tmp2=head;
            while(cur){
                if(cur->val<x){
                    tmp1->next=cur;
                    tmp1=head;
                }
                else{
                    tmp2->next=cur;
                    tmp2=cur;
                }
                cur=cur->next;
            }
            tmp1->next=tmp2;
            return head->next;        
        }
    };
    // 可以AC,但是时间效率太差
    // 这个也就是我的解题思路
    ListNode *partition(ListNode *head, int x) {
        ListNode node1(0), node2(0);   // 学会如何定义一个空结点???
        ListNode *p1 = &node1, *p2 = &node2;
        while (head) {
            if (head->val < x)
                p1 = p1->next = head;
            else
                p2 = p2->next = head;
            head = head->next;
        }
        p2->next = NULL;
        p1->next = node2.next; //注意结点这只能.next 不能->next;
        return node1.next;
    }
    

    203.Remove Linked List Elements

    // 链表中结点的删除
    /*
     * 注意多种情况的讨论
     * 1.链表只有一个结点,删除后,头结点要指向null
     * 2.删除的结点是 尾结点
     * 3.正常结点进行删除
     */
    // 结构化定义结点
    struct ListNode
    {
        int m_value;
        ListNode *next;
    };
    void deleteLinkListNode(ListNode ** pListHead,ListNode *pToBeDeleted){
        if(pListHead==NULL)
            return;
        // 借用下一个结点,来覆盖删除本结点,非常好用的方法。
        if(pToBeDeleted->next!=NULL){
            ListNode p_next=pToBeDeleted->next;
            pToBeDeleted->m_value=p_next->m_value;
            pToBeDeleted->next=p_next->next;
            // 释放空结点
            delete p_next;
            p_next=NULL
    
        }
        // 如果只有一个结点
        else if(*pListHead==pToBeDeleted){
            delete pToBeDeleted;
            pToBeDeleted=NULL;
            *pListHead=NULL;
        }
        // 删除尾结点
        else{
            ListNode cur_node=*pListHead;
            // 一个一个传递找到尾结点
            while(cur_node->next!=pToBeDeleted){
                cur_node=cur_ndoe->next;
            }
            cur_node->next=NULL;
            // 删除释放结点
            delete pToBeDeleted;
            pToBeDeleted=NULL;
    
        }
    }
    
    ListNode *removeElements(ListNode *head, int val)
    {
        ListNode **list = &head;
    
        while (*list != nullptr)
        {
            if ((*list)->val == val)
            {
                *list = (*list)->next;
            }
            else
            {
                list = &(*list)->next;
            }
        }
    
        return head;
    }
    
    //class Solution {
    public:
        ListNode* removeElements(ListNode* head, int val) {
            ListNode* pre = NULL;
            ListNode* loop = head;
            while(loop) {
                if (loop->val == val) {
                    if (pre == NULL) {
                        head = loop->next;
                        delete loop;
                        loop = head;
                    } else {
                        pre->next = loop->next;
                        delete loop;
                        loop = pre->next;
                    }
                } else {
                    pre = loop;
                    loop  = loop->next;
                }
            }
            return head;
        }
    };
    
    // 还有一个递归的思路
    // 这个估计不能应用于循环链表,必须有一个结束递归的条件(尾指针为NULL)
    class Solution {
    public:
        ListNode* removeElements(ListNode* head, int val) {
            if (head == NULL) return NULL;
            head->next = removeElements(head->next, val);
            return head->val == val ? head->next : head;
        }
    };
    // 新建一个 dummy伪结点,将头结点放在伪结点后面,修改伪结点以后的元素
    class Solution {
    public:
        ListNode* removeElements(ListNode* head, int val) {
            // more easy 
            ListNode *dummy=new ListNode(0);
            dummy->next=head;    //伪结点连接上头结点
            head=dummy;             // 伪结点作为头结点,只修改伪结点以后的结点,伪结点是不改变的,最后进行返回即可
            while(head->next!=NULL){
                if(head->next->val==val){
                    head->next=head->next->next;
                }
                else{
                    head=head->next;
                }
            }
            return dummy->next;
        }        
    };
    

    328.Odd Even Linked List

    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    // 这个需要记忆,就是方法的纯记忆
    class Solution {
    public:
        ListNode* oddEvenList(ListNode* head) {
            if(head==NULL)
                return head;
            else{
                ListNode *odd=head,*even=head->next,*dummy_even=even;  //保留原始的偶结点初结点
                while(even && even->next){
                    odd->next=odd->next->next;
                    even->next=even->next->next;
                    odd=odd->next;
                    even=even->next;
                }
                odd->next=dummy_even;
            }
            return head;
            
        }
    };
    

    817.Linked List Components

    // 我的思路:1.先判断两个元素
    //                2.判断这个两个元素是否同时在这个G中(我当时想到了循环判断个python中的字典变量)
    //                但是没有想到c++中可以利用关联容器来进行实现
    class Solution {
    public:
        int numComponents(ListNode* head, vector<int>& G) {
            unordered_set<int> G_set (G.begin(),G.end());    //创建一个关联容器 set,并且使用哈希函数组织的set
            int result=0;
            while(head){
                if(G_set.count(head->val) && (head->next==NULL || !G_set.count(head->next->val))) // .count()函数返回0,1 int值 ,表示key是否存在
                    result++;
                head=head->next;
            }
            return result;        
        }
    };
    

    23.Merge k Sorted Lists

    // 按照自己的想法来写的
    // 现将所有的链表值 放入一个vector中
    // 排序后,再新建一个链表,将点一个个再添加到链表的tail
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            vector<int> container;
            for(int i=0;i<lists.size();i++){
                while(lists[i]){
                    container.push_back(lists[i]->val);
                    lists[i]=lists[i]->next;
                }
            }
            vector<int> sort (container.begin(),container.end());  //这返回一个iterator而不是一个排好序的vector  就是这一个问题
            ListNode *head=new ListNode(0);
            ListNode *dummy=head;
            for(int i=0;i<sort.size();i++){
                ListNode *node=new ListNode(0);
                node->val=sort[i];
                node->next=NULL;
                head->next=node;
                head=node;
            }
            return dummy->next;      
        }
    }; 
    // 还是自己的想法,简单的进行修改
    //修改通过版,20ms, faster  than 70%
    // 还要进行时间和空间复杂度的分析 
    // O(m x n) m是行数,n是一个链表最多的个数
    class Solution {
    public:
        ListNode* mergeKLists(vector<ListNode*>& lists) {
            vector<int> con;
            for(int i=0;i<lists.size();i++){
                while(lists[i]){
                    con.push_back(lists[i]->val);
                    lists[i]=lists[i]->next;
                }
            }
            std::sort(con.begin(),con.end());  直接使用标准库的排序来实现升序排序
            ListNode *head=new ListNode(0);
            ListNode *dummy=head;
            for(int i=0;i<con.size();i++){
                ListNode *node=new ListNode(0);
                node->val=con[i];
                node->next=NULL;
                head->next=node;
                head=node;
            }
            return dummy->next; 
        }
    };
    // 50ms
    // 一个基于 merge two sortd list的解法,很有思想
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        if(lists.empty()){
            return nullptr;
        }
        while(lists.size() > 1){
            lists.push_back(mergeTwoLists(lists[0], lists[1]));
            lists.erase(lists.begin());
            lists.erase(lists.begin());
        }
        return lists.front();
    }
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        if(l1 == nullptr){
            return l2;
        }
        if(l2 == nullptr){
            return l1;
        }
        if(l1->val <= l2->val){
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }
        else{
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    }       
    

    725.Split Linked List in Parts

    // 自己的想法
    class Solution {
    public:
        vector<ListNode*> splitListToParts(ListNode* root, int k) {
            vector<ListNode*>result;
            int number=0;
            while(root){
                root=root->next;
                number++;
            }
            if(number<=k){
                for(int i=0;i<k;k++){
                    if(root!=NULL){
                        ListNode*tmp=root;
                        root=root->next;
                        result.push_back(tmp);
                    }
                    // 接入空结点
                    else{
                        ListNode *tmp=new ListNode();
                        result.push_back(tmp);
                    }        
                }
            }
           //问题在于当这个链表中的元素大于要分隔的部分个数时,如何进行 切分链表中的元素
          // 是用循环,还是利用指针??
            else{
               
            }
            
        }
    };
    
    // 参考一下别人的版本
    class Solution {
    public:
        vector<ListNode*> splitListToParts(ListNode* root, int k) {
            vector<ListNode*> parts(k, nullptr);
            int len = 0;
            for (ListNode* node = root; node; node = node->next)   // 这个改成while循环就不对,需要深度思考一下
                len++;
            int n = len / k, r = len % k; // n : minimum guaranteed part size; r : extra nodes spread to the first r parts;
            ListNode* node = root, *prev = nullptr;
            for (int i = 0; node && i < k; i++, r--) {
                parts[i] = node;
                for (int j = 0; j < n + (r > 0); j++) {
                    prev = node;
                    node = node->next;
                }
                prev->next = nullptr;
            }
            return parts;
        }
    };
    

    148.Sort List

    //这道题1.分而治之的思想2.递归的思想3.两个有序链表合并 都需要仔细的去学习理解
    /**
     * 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;
            // clac the linked list length
            ListNode *cur=head;
            int length=0;
            while(cur){
                cur=cur->next;
                length++;
            }
            ListNode dummy(0);
            dummy.next=head;
            ListNode *left,*right,*tail;
            for(int step=1;step<length;step<<=1){  // step<<=1 loop的含义?
                cur=dummy.next;
                tail=&dummy;
                while(cur){
                    left=cur;
                    right=split(left,step);
                    cur=split(right,step);
                    tail=merge(left,right,tail);
                }
            }
            return dummy.next;
        }
    private:
        ListNode *split(ListNode *head,int n){
            for(int i=1;i<n&&head;i++) head=head->next;
            if(!head) return NULL;
            ListNode *second=head->next;
            head->next=NULL;
            return second;
        }
        ListNode *merge(ListNode *l1,ListNode *l2,ListNode *head){
            ListNode *cur=head;
            while(l1&&l2){
                if(l1->val>l2->val){
                    cur->next=l2;
                    cur=l2;
                    l2=l2->next;
                }
                else{
                    cur->next=l1;
                    cur=l1;
                    l1=l1->next;
                }
            }
            cur->next=(l1?l1:l2);
            while(cur->next)
                cur=cur->next;
            return cur;
        }
    };
    // 当然合并两个有序链表,还有一种简单容易理解的方法
    ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) {
        if(l1 == nullptr){
            return l2;
        }
        if(l2 == nullptr){
            return l1;
        }
        if(l1->val <= l2->val){
            l1->next = mergeTwoLists(l1->next, l2);
            return l1;
        }
        else{
            l2->next = mergeTwoLists(l1, l2->next);
            return l2;
        }
    } 
    

    430.Flatten a multilevel Doubly Linked List

    /*
    // Definition for a Node.
    class Node {
    public:
        int val = NULL;
        Node* prev = NULL;
        Node* next = NULL;
        Node* child = NULL;
    
        Node() {}
    
        Node(int _val, Node* _prev, Node* _next, Node* _child) {
            val = _val;
            prev = _prev;
            next = _next;
            child = _child;
        }
    };
    */
    // 自己理解深度还是有一点差距的
    // 自己可以想清楚这个思路的完成
    // 但是一转换到代码的实现,就会出现很多错误和过不去的“坎”
    class Solution {
    public:
        Node* flatten(Node* head) {
            Node *cur=head;
            Node *cur_next;
            while(cur)
            {
                if(cur->child){
                    cur_next=cur->next;
                    cur->next=flatten(cur->child);
                    cur->child=NULL;     // 一维后 all child become null
                    cur->next->prev=cur;  //双向链表的链接
                    while(cur->next){
                        cur=cur->next;
                    }
                    cur->next=cur_next;
                    if(cur_next){
                        cur_next->prev=cur; // 双向链表的链接
                    }
                }
                else{
                    cur=cur->next;
                }
               
            }
            return head;
            
        }
    };
    

    109.convert the sort list to heigh balanced BST

    // perfect code 
    /**
     * Definition for singly-linked list.
     * struct ListNode {
     *     int val;
     *     ListNode *next;
     *     ListNode(int x) : val(x), next(NULL) {}
     * };
     */
    /**
     * Definition for a binary tree node.
     * struct TreeNode {
     *     int val;
     *     TreeNode *left;
     *     TreeNode *right;
     *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
     * };
     */
    class Solution {
    public:
        TreeNode* sortedListToBST(ListNode* head) {
            return RecursionListToBST(head,NULL);
        }
        TreeNode* RecursionListToBST(ListNode* head,ListNode *tail){
            // linklist is empty
            if(head==tail)
                return NULL;
            // only one node in the tree
            if(head->next==tail){
                TreeNode *root=new TreeNode(head->val);
                return root;
            }
            // search the middle node 
            // excllent code segment need memorize.
            ListNode *mid=head;
            ListNode *temp=head;
            while(temp!=tail && temp->next!=tail){
                mid=mid->next;
                temp=temp->next->next;
            }
            TreeNode *root=new TreeNode(mid->val);
            root->left=RecursionListToBST(head,mid);
            root->right=RecursionListToBST(mid->next,tail);
            return root;
        }
    };
    

    /*
     * 分析思路:
     * 1.当链表的长度大于k的时候,直接返回原链表,输入的k是小于等于链表的长度
     * 2.现将链表分成k个groups,对每个groups中的内容进行反转
     * 3.在保留原结点(dummy)的情况下,再将结点进行结合起来
     */
    
    // 主要是虚结点dummy node 的设立
    // 还有就是 编写 reverse list
    // 用递归的方法来解决感觉好一点
    /**
     * 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) {
            auto node=head;
            for(int i=0;i<k;++i){
                if(!node)
                    return head;
                node=node->next;
            }
            auto new_head=reverse(head,node);
            head->next=reverseKGroup(node,k);
            return new_head;
        }
    private:
        ListNode *reverse(ListNode *first,ListNode *last){
            ListNode *prev=last;
            // 交换元素这一块,不是很懂 看的有点懵
            while(first!=last){
                auto temp=first->next;
                first->next=prev;
                prev=first;
                first=temp;
            }
            return prev;
        }
    };
    
    // 这个解法是利用循环iteration 来实现
    // 但是效率并没有比递归好很多,只是有一点点改进
    class Solution {
    public:
        ListNode *reverseKGroup(ListNode *head, int k) {
            if(head==NULL||k==1) return head;
            int num=0;
            ListNode *preheader = new ListNode(-1);
            preheader->next = head;
            ListNode *cur = preheader, *nex, *pre = preheader;
            while(cur = cur->next) 
                num++;
            while(num>=k) {
                cur = pre->next;
                nex = cur->next;
                for(int i=1;i<k;++i) {
                    cur->next=nex->next;
                    nex->next=pre->next;
                    pre->next=nex;
                    nex=cur->next;
                }
                pre = cur;
                num-=k;
            }
            return preheader->next;
        }
    };
    
    

    关于链表的一些问题
    1.reverse linklist 注意结点的反转存储的问题
    2.partition linklist dummy结点的巧妙运用
    3.reverse linklist ii java,C++是两种完全不同的实现方法

    不要用狭隘的眼光看待不了解的事物,自己没有涉及到的领域不要急于否定. 每天学习一点,努力过好平凡的生活.
  • 相关阅读:
    大型网站架构之分布式消息队列【转】
    Jpa生成mysql注释,添加ODBC数据源导入数据到EA
    Spring boot框架项目,使用maven命令将配置文件打包到jar包外,项目运行读取jar外配置文件
    spring boot 整合 quartz 集群环境 实现 动态定时任务配置【原】
    关于博主
    [School Life] 骗你去努力
    [OI
    洛谷P4994【终于结束的起点】
    [OI系列]在考场千万不能犯的错误
    [OI
  • 原文地址:https://www.cnblogs.com/GeekDanny/p/9726806.html
Copyright © 2011-2022 走看看