<手撕链表系列>-链表回文/链表相交

76 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路

前言

本系列主要讲解链表的经典题

注:划重点!!必考~

链表分割

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

  • 题目描述:

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

  • 解题思路:
  1. 这里我们先找到中间结点(使用快慢指针法)
  2. 快指针每次走两个结点的位置,慢指针每次走一个结点的位置
  3. 快指针走到结束位置时,慢指针恰到中间位置
  4. 从中间结点开始对接下来每个结点进行改变结点方向
  5. 最后对两个头结点开始逐个遍历接下来的结点,直到相遇
  • 图示:

​编辑

​编辑

  • 参考代码:
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
        //快慢指针找到中间结点
        struct ListNode*fast=A,*slow=A;
        while(fast&&fast->next)
        {
            fast=fast->next->next;
            slow=slow->next;
        }
        struct ListNode*cur=slow;
        //两个指针用来逆转节点方向
        struct ListNode*prev=NULL,*next;
        while(cur)
        {
            struct ListNode*Next=cur->next;
            cur->next=prev;
            prev=cur;
            cur=Next;
        }
        //遍历比较
        struct ListNode*cur1=A,*cur2=prev;
        while(cur1&&cur2)
        {
            if(cur1->val==cur2->val)
            {
                cur1=cur1->next;
                cur2=cur2->next;
            }
            else
                return false;
        }
        return true;
    }
};

  • 结果:

链表相交

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

  • 题目描述:

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

  • 示例:

​编辑

  • 提示:
  • listA 中节点数目为 m
  • listB 中节点数目为 n
  • 0 <= m, n <= 3 * 104
  • 1 <= Node.val <= 105
  • 0 <= skipA <= m
  • 0 <= skipB <= n
  • 如果 listA 和 listB 没有交点,intersectVal 为 0
  • 如果 listA 和 listB 有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]
  • 解题思路:
  1. 对两个链表进行分别遍历算出长度差
  2. 同时如果两链表末尾结点地址不同,则表示没有两链表没有相交
  3. 对长链表指针先走长度差个结点,再两个指针同时遍历
  4. 当两个结点指针相遇时即为相交节点
  • 参考代码:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    //创建寻址指针
    struct ListNode*cur1=headA,*cur2=headB;
    //计算各链表的长度
    int len1=1,len2=1,gas;
    while(cur1->next)
    {
        len1++;
        cur1=cur1->next;
    }
    while(cur2->next)
    {
        len2++;
        cur2=cur2->next;
    }
    //各链表尾节点不相等则两链表不相交
    if(cur1!=cur2)
    return false;
    //接下来则是必定有相交节点的情况
    //判断长短并记录
    struct ListNode*geater,*less;
    if(len1>=len2)
    {
        geater=headA;
        less=headB;
        gas=len1-len2;
    }
    else
    {
        geater=headB;
        less=headA;
        gas=len2-len1;
    }
    //长链表先走差距长度
    while(gas--)
    {
        geater=geater->next;
    }
    //一同走,相等时则找到相交节点
    while(geater!=less)
    {
        geater=geater->next;
        less=less->next;
    }
    return geater;
}

  • 结果: