链表算法题讲解

前言

学会了链表,就需要在算法题上面进行实践

1.删除结点

思路:创建一个新的链表,遍历原链表,将不等于val的结点输入到新链表中。

注意:在输入第一个结点的时候需要判断是否为空。

为避免进入死循环,需要将新链表的尾结点的next指针置为NULL。

代码如下:

2.反转链表

思路1:新建一个链表,遍历旧链表,依次头插到新链表中。

思路2:运用三个指针思路,实现反转。(不需要创建新链表)这个思路不好想,可以记忆。

这里实现第二个思路,第一个思路读者可以下去自己实现。

原理:

设置三个指针,分别指向NULL,head,head->next。将n2->next指向n1,随后各往后走一步,即n1 = n2,n2= n3,n3 = n3->next,再循环n1 = n2,n2= n3,n3 = n3->next。但需要判断n3是否为空,如果为空便不往后走了,当n2为空的时候,n1便是反转链表的头指针。

代码如下:

3.寻找中间结点

思路:这是典型的快慢指针问题。通过设置两个指针,slow和fast。slow指针每次走一步,fast指针每次走两步。当fast指针走到结尾或者变为空时,此时的slow指针便是中间结点。

4.返回倒数第K个结点

思路1:运用快慢指针实现。让fast指针先走k步,然后slow和fast一起走,当fast走到结尾时,slow指针便是结果

思路2:将指针逆置,再从头结点开始算K。

这里实现第二个思路:

5.合并有序链表

思路:创建一个空链表,从头遍历两个旧链表,每次判断,小的结点放到新的链表中,然后该链表继续后移。依次重复直到有一个链表为空。最后将不为空的链表放到新链表的后面。

由于代码过长不好截图,这里贴一下代码:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {

    ListNode * newhead , * newtail;

    newhead = newtail = (ListNode * )malloc(sizeof(ListNode ));

    if(list1 ==NULL)

    {

        return list2;

    }

    if(list2 == NULL)

    {

        return list1;

    }

    else{

while(list1&&list2)

    {

        if(list1->val>list2->val)

        {

            newtail->next = list2;

            newtail = newtail->next;

            list2 =list2->next;

        }

        else

        {

            newtail->next = list1;

            newtail = newtail->next;

            list1 =list1->next;

        }

    }

    if(list1)

    {

        newtail->next = list1;

    }

    if(list2)

    {

        newtail->next = list2;

    }

    ListNode * pcur = newhead->next;

    free(newhead);

    newhead = NULL;

    return pcur;

    }

}

6.切割链表

思路:分别创建两个链表,将大于x的结点放到一个链表中,小于x的结点放到另一个结点中。最后将小链表的尾结点指向大链表的头结点。

代码如下:

7.判断是否为回文结构

思路1:新建一个数组,将每个值都存放在数组中,然后设置一个left = 0指针和right = size-1指针,分别从两端进行判断。(不满足空间复杂度,仅供参考)

思路2:找到中间结点,然后将中间结点以及后面的进行逆置,从后半段的头指针与前半段的头指针开始遍历比较。

代码如下:

ListNode * SLfindmid(ListNode * head)

{

    if(head == NULL)

    {

        return NULL;

    }

    ListNode * slow,* fast;

    slow = fast = head;

    while(fast&&fast->next)

    {

        fast  = fast->next->next;

        slow = slow ->next;

    }

    return slow;

}

ListNode * reverse(ListNode * head)

{

    if(head == NULL)

    return NULL;

    ListNode * n1,*n2,*n3;

    n1 = NULL;

    n2 = head;

    n3 = head->next;

    while(n2)

    {

        n2->next = n1;

        n1 = n2;

        n2 = n3;

        if(n3)

        n3 = n3->next;

    }

    return n1;

}

class PalindromeList {

public:

    bool chkPalindrome(ListNode* A) {

        // write code here

        //找中间结点

        ListNode * mid =  SLfindmid(A);

        //逆置后面的链表

        ListNode * pcur =  reverse(mid);

        //进行判断

        while(pcur&&mid)

        {

            if(pcur->val == A->val)

            {

            pcur= pcur->next;

            A = A->next;

            }

            else

             {

            return false;

            }

           

        }

        return true;

    }

};

8.判断相交链表

思路:先分别计算两个链表的长度,求其差的绝对值,让长的链表先走绝对值步,再一起向后遍历。

代码如下:

9. 判断是否为环

思路:运用快慢指针。还是慢指针走一步,快指针走两步,如果两个指针能相遇,那一定是环形的,如果快指针走到NULL,那便不是环形。

代码如下:

10.判断是否为环2

思路:快慢指针找到相遇的结点。再让头指针从头开始遍历与此同时相遇结点往后走,头指针和结点相遇的结点就是就是入环点。

代码如下:

11. 进行链表的深拷贝

思路:

1.在原链表基础上复制链表

*2.连接random指针(copy->random) = pcur->random->next;)

3.断开连接   

代码如下:

typedef struct Node Node;

Node * buynode(int val)//申请新节点

{

    Node* newnode = (Node* )malloc(sizeof(Node));

    newnode->val = val;

    newnode->next = newnode->random = NULL;

    return newnode;

}

void add(Node * head)//添加copy

{

    Node * pcur = head;

    while(pcur)

    {

  Node *  newnode = buynode(pcur->val);

  newnode->next = pcur->next;

  pcur->next = newnode;

  pcur = pcur->next->next;

    }

}

struct Node* copyRandomList(struct Node* head) {

    if(head ==NULL)

    return NULL;

    //1.产生连接,复制链表

    add(head);

    //2.连接random

    Node * pcur = head;

    while(pcur)

    {

        Node* copy = pcur->next;

        if(pcur->random)

        copy->random = pcur->random->next;

        pcur = copy->next;

    }

    //3.断开链接

    Node *  newhead = head->next;

     Node *  newtail = head->next;

     pcur = head;

     while(pcur->next->next)

     {

        pcur = pcur->next->next;

        newtail->next = pcur->next;

        newtail = newtail->next;

     }

     return newhead;

}

12.作者的话

如果读者对代码或者思路不解的话,可以私信作者哦

  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值