【刷题系列】链表经典OJ题(二)

简介: 【刷题系列】链表经典OJ题(二)

需要的请点下面:

-> 给大家推荐一款很火爆的刷题、面试求职网站 <-
文章题目来源力扣或牛客
🎈 力扣(LeetCode)全球极客挚爱的技术成长平台
LeetCode官网: https://leetcode-cn.com/problem-list/e8X3pBZi/
牛客网-笔试题库:[ https://www.nowcoder.com
]( https://www.nowcoder.com)
在这里插入图片描述
  1. 回文链表
  2. 相交链表
  3. 环形链表丨
  4. 环形链表II
  5. 复制带随机指针的链表

7.回文链表

来源:牛客网
链接: OJ链接

在这里插入图片描述

  • ✨思路

先找到中间节点,把后半部分逆置,然后再依次比较是否相等

struct ListNode* reverseList(struct ListNode* head){

    struct ListNode*n1=NULL,*n2=head;
    while(n2)
    {
        struct ListNode*n3=n2->next;
        n2->next=n1;
        n1=n2;
        n2=n3;
    }
    return n1;
}
    struct ListNode* middleNode(struct ListNode* head){
    struct ListNode*slow=head,*fast=head;
    while(fast && fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
    }
    return slow;
}
    bool chkPalindrome(ListNode* A) {
        // write code here
        struct ListNode* mid=middleNode(A);//找中间节点
        struct ListNode*cur2=reverseList(mid);//从中间节点开始逆置
        struct ListNode*cur1=A;
        while(cur2)//依次比较
        {
            if(cur1->val!=cur2->val)
                return false;
            cur2=cur2->next;
            cur1=cur1->next;
        }
        
        return true;
    }
在这里插入图片描述

8.相交链表

来源:力扣(LeetCode)
链接: https://leetcode.cn/problems/intersection-of-two-linked-lists

在这里插入图片描述

  • ✨思路

仔细观察可以发现,如果链表相交的话,那么它们都有一个共同的特点,那就是尾节点相同,所以可以利用这个特点来解决链表是否相交
至于返回相交点,我们可以依次算出每一个链表的长度,然后让长的那个一个先走差距步,然后再同时走,直到相等即为相交点

在这里插入图片描述

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {

    struct ListNode* cur1=headA,*cur2=headB;
    int count1=1,count2=1;
    //找尾
    while(cur1->next)
    {
        cur1=cur1->next;
        count1++;
    }
    while(cur2->next)
    {
        cur2=cur2->next;
        count2++;
    }
    //尾节点不相等则不相交
    if(cur1!=cur2)
        return NULL;

    struct ListNode*longList=headA,*shotList=headB;
    if(count1 < count2 )
    {
        longList=headB;
        shotList=headA;
    }
    int k=abs(count1-count2);
    //让长的先走差距步
    while(k--)
    {
        longList=longList->next;
    }
    //相等地方即为入口
    while(longList!=shotList)
    {
        longList=longList->next;
        shotList=shotList->next;
    }
    return longList;

}
在这里插入图片描述

9.环形链表丨

来源:力扣(LeetCode)
链接: https://leetcode.cn/problems/linked-list-cycle

在这里插入图片描述

  • ✨思路

快慢指针法:定义两个指针fast和slow,fast一次走两步,slow一次走一步,最后如果相等则说明存在环,如果fast遇到NULL,则说明没有环
证明:
在这里插入图片描述

bool hasCycle(struct ListNode *head) {
    struct ListNode*fast,*slow;
    fast=slow=head;
    while(fast && fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(slow==fast)
            return true;
    }
    return false;
}
在这里插入图片描述

10.环形链表 II

来源:力扣(LeetCode)
链接: https://leetcode.cn/problems/linked-list-cycle-ii
在这里插入图片描述
  • ✨思路一

快慢指针法:定义两个指针fast和slow,fast一次走两步,slow一次走一步,相等位置为相遇点,在相遇点断开,转化成两个链表相交求交点问题

在这里插入图片描述

  • ✨思路二

这个解法很妙,就是从找到相遇点后,一个指针从相遇点开始,另一个指针从头开始,同时遍历,直到相等就是入环点,这个可以用数学公式证明

在这里插入图片描述

//思路二的代码实现
struct ListNode *detectCycle(struct ListNode *head) {
        struct ListNode*fast,*slow;
    fast=slow=head;
    while(fast && fast->next)
    {
        fast=fast->next->next;
        slow=slow->next;
        if(slow==fast)//有环
        {
            struct ListNode*cur=head;
            while(cur!=slow)//入口点
            {
                cur=cur->next;
                slow=slow->next;
            }
            return cur; 
        }
    }
     return NULL;

}
在这里插入图片描述

11.复制带随机指针的链表

来源:力扣(LeetCode)
链接: https://leetcode.cn/problems/copy-list-with-random-pointer
在这里插入图片描述
  • ✨思路

这题主要的难点在于随机指针random的复制,搞定了这个随机指针,那么问题就迎刃而解了
首先,我们可以把每一个复制节点的尾插到每一个原节点的后面,然后依次根据原节点的random把复制节点的random连接上,最后再恢复原链表,取复制链表


在这里插入图片描述


struct Node* copyRandomList(struct Node* head) {
    struct Node* cur=head,*next=head,*copy=NULL;
    //复制节点尾插到原节点中
    while(cur)
    {
        next=cur->next;
        copy=(struct Node*)malloc(sizeof(struct Node));
        copy->val=cur->val;
        cur->next=copy;
        copy->next=next;
        
        //迭代
        cur=next;
    }
    //复制randam
    cur=head;
    while(cur)
    {
        copy=cur->next;
        next=cur->next->next;
        if(cur->random==NULL)
        {
            copy->random=NULL;
        }
        else
        {
            copy->random=cur->random->next;
        }
        //迭代
        cur=next;
    }

    //恢复原链表
    struct Node*copyhead=NULL,*tail=NULL;
    cur=head;
    while(cur)
    {
        copy=cur->next;
        next=cur->next->next;
        if(copyhead==NULL)
        {
            copyhead=tail=copy;
        }
        else
        {
            tail->next=copy;
            tail=tail->next;
        }
        cur->next=next;
        //迭代
        cur=next;
    }
    return copyhead;
}

在这里插入图片描述




相关文章
|
4月前
|
程序员
【刷题记录】移除链表元素
【刷题记录】移除链表元素
|
4月前
|
索引 Python
【Leetcode刷题Python】328. 奇偶链表
在不使用额外空间的情况下,将链表中的奇数和偶数索引节点重新排序的方法,并提供了相应的Python实现代码。
35 0
|
2月前
|
存储 Java
数据结构第三篇【链表的相关知识点一及在线OJ习题】
数据结构第三篇【链表的相关知识点一及在线OJ习题】
26 7
|
4月前
|
Python
【Leetcode刷题Python】114. 二叉树展开为链表
LeetCode上114号问题"二叉树展开为链表"的Python实现,通过先序遍历二叉树并调整节点的左右指针,将二叉树转换为先序遍历顺序的单链表。
29 3
【Leetcode刷题Python】114. 二叉树展开为链表
|
4月前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
54 5
|
4月前
|
Python
【Leetcode刷题Python】剑指 Offer 18. 删除链表的节点
Leetcode题目"剑指 Offer 18. 删除链表的节点"的Python解决方案,通过使用双指针法找到并删除链表中值为特定数值的节点,然后返回更新后的链表头节点。
43 4
|
4月前
|
存储 Python
【Leetcode刷题Python】23. 合并K个升序链表
合并K个升序链表的方法:使用数组排序的暴力求解法、使用小顶堆的高效方法,以及分而治之的策略,并提供了相应的Python实现代码。
21 1
|
4月前
|
机器学习/深度学习
【刷题记录】相交链表
【刷题记录】相交链表
|
4月前
【刷题记录】链表的中间结点
【刷题记录】链表的中间结点