链表_数据结构

Linked List

目录

环形链表实现
// 使用环形链表的数据结构来实现
// 首尾结点的链接很机智,可以学习
#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++是两种完全不同的实现方法

转载于:https://www.cnblogs.com/GeekDanny/p/9726806.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值