LeetCode经典链表OJ题<二>

 

目录

一、链表的回文结构

 二、相交链表

三、环形链表

四、复制带随机指针的链表


一、链表的回文结构

题目介绍:

LeetCode经典链表OJ题<二>_第1张图片

题目链接 :​​​​​​链表的回文结构_牛客题霸_牛客网 (nowcoder.com)

此题目看起来有点儿难度,但是如果你学习了《返回链表的中间结点》和《反转链表》后,你会如鱼得水。只要灵活运用前边两个知识点,这道题很轻松就解决了。 首先我们运用返回链表的中间结点找到此链表的中间结点,然后让此结点后面的所有结点包括此结点进行反转链表从而得到一个链表,另一个链表是中间结点前边的链表。将这两个链表分别遍历,如果有某个结点不相等,说明不是回文结构,若处处相等则是回文结构。直接解释的话可能会有一些抽象,接下来我们用图解进行分析:

LeetCode经典链表OJ题<二>_第2张图片

 LeetCode经典链表OJ题<二>_第3张图片

代码如下:

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
struct ListNode* reverseList(struct ListNode* head)
{
   if(head==NULL)
   {
       return NULL;
   }
   struct ListNode* cur=head;
   struct ListNode* phead=NULL;
   while(cur)
   {
       struct ListNode*next=cur->next;
       cur->next=phead;
       phead=cur;
       cur=next;
   }
   return phead;
}
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        ListNode* fast=A;
        ListNode* slow=A;
        while(fast&&fast->next)
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        ListNode* mid=reverseList(slow);
        while(A&&mid)
        {
            if(A->val==mid->val)
            {
                A=A->next;
                mid=mid->next;
            }
            else
            {
                return false;
            }
        }
        return true;
        
    }
};

 二、相交链表

题目介绍:

LeetCode经典链表OJ题<二>_第4张图片

 题目链接:160. 相交链表 - 力扣(LeetCode) (leetcode-cn.com)

首先分别遍历这两个链表,计算出这两个链表分别有几个结点,然后算出他们相差几个结点,让比较长的链表先移动他们相差的结点数,再同时遍历,当list1=list2时,就找到了他们的公共点,若一直到最后都没找到,则返回NULL,接下来看图解:

LeetCode经典链表OJ题<二>_第5张图片

 

 LeetCode经典链表OJ题<二>_第6张图片

 

LeetCode经典链表OJ题<二>_第7张图片

 代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    int a=0,b=0,c=0;
    struct ListNode *l1=headA;
    struct ListNode *l2=headB;
    while(headA)
    {
        a++;
        headA=headA->next;
    }
    while(headB)
    {
        b++;
        headB=headB->next;
    }
    c=abs(a-b);
    if(anext;
        }
    }
      else
    {
        while(c--)
        {
            l1=l1->next;
        }
    }
    while(l1&&l2)
    {
        if(l1==l2)
        {
            return l1;
        }
        else
        {
            l1=l1->next;
            l2=l2->next;
        }
    }
    return NULL;
    
}

三、环形链表

题目介绍:

LeetCode经典链表OJ题<二>_第8张图片

题目链接:142. 环形链表 II - 力扣(LeetCode) (leetcode-cn.com) 

此题逻辑性很强,首先此链表是一个环形链表,运用快慢指针可以找到他们在环中相遇的结点位置。(快指针走两步,慢指针走一步)接下来请看图解:

LeetCode经典链表OJ题<二>_第9张图片

 由于fast走两步slow走一步所以可得公式 2(L+x)=n*c+x+L  n代表圈数 c代表圈长

化简得:L+x=n*c  当n=1时  L=c-x  也就是说 如果定义两个指针一个从头遍历,一个从相遇的地方遍历那么他们刚好在交点处相遇,由此关系可编辑代码。

图解如下:

LeetCode经典链表OJ题<二>_第10张图片

 代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *detectCycle(struct ListNode *head)
{
    struct ListNode *fast=head;
    struct ListNode *slow=head;
    while(fast&&fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(fast==slow)
        {
            struct ListNode *meetNode=slow;
            while(meetNode!=head)
            {
                meetNode=meetNode->next;
                head=head->next;
            }
            return head;
        }
    }
    return NULL;
    
}

四、复制带随机指针的链表

题目介绍:

LeetCode经典链表OJ题<二>_第11张图片

 题目链接:138. 复制带随机指针的链表 - 力扣(LeetCode) (leetcode-cn.com)

首先在每一个结点后面插入一个新结点,由图所示:

LeetCode经典链表OJ题<二>_第12张图片

 然后去寻找每一个新结点的random值,新结点的random等于旧结点random的next;也就是当cur等于旧结点时,copy->random=cur->random->next;

LeetCode经典链表OJ题<二>_第13张图片

 最终再把一个个新结点从旧结点上边解下来。

代码如下:

/**
 * Definition for a Node.
 * struct Node {
 *     int val;
 *     struct Node *next;
 *     struct Node *random;
 * };
 */

struct Node* copyRandomList(struct Node* head) 
{
    struct Node*cur=head;
	//将新结点链接到原结点后面
    while(cur)
    {
        struct Node*next=cur->next;
        //开辟新结点并且赋val值
        struct Node*copy=(struct Node*)malloc(sizeof(struct Node));
        copy->val=cur->val;

        //插入数据
        cur->next=copy;
        copy->next=next;

        //迭代往下走
        cur=next;

    }
    //置新结点的random
    cur=head;
    while(cur)
    {
        struct Node*copy=cur->next;
        if(cur->random!=NULL)
        copy->random=cur->random->next;
        
        else
        {
            copy->random=NULL;
        }
        cur=copy->next;
    }
    //解拷贝结点,链接拷贝结点
    cur=head;
    struct Node*copyTail=NULL;
    struct Node*copyHead=NULL;
    while(cur)
    {
    
    struct Node* copy=cur->next;
    struct Node* next=copy->next;
        if(copyTail==NULL)
    copyTail=copyHead=copy;
    else
    {
        copyTail->next=copy;
        copyTail=copy;
    }
    cur->next=next;
    cur=next;
    

    }
    return copyHead;

}

你可能感兴趣的:(数据结构,链表,数据结构)