初始数据结构——链表OJ

1.相交链表

        题目链接:相交链表icon-default.png?t=N7T8https://leetcode.cn/problems/merge-two-sorted-lists/description/

 

先看代码


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode ListNode;
struct ListNode* getIntersectionNode(struct ListNode* headA,
                                     struct ListNode* headB) {
    if (headA == NULL || headB == NULL)
        return NULL;
    ListNode *pa, *pb;
    pa = headA, pb = headB;
    while (pa != pb) {
        pa = (pa!=NULL) ? pa->next : headB;
        pb = (pb!=NULL) ? pb->next : headA;
    }
    return pa;
}

 

 

 

 思路:

        解决这个问题我们可以采用双指针法:

  1. 先判断两个链表的头节点是否为空,其中一个为空则说明两个链表不可能相交直接返回NULL;
  2. 创建两个指针pa和pb分别指向headA和headB
  3. 进入循环,以pa和pb相等作为循环条件,在循环中考虑pa和pb为空的情况,如果pa走到了空,就让pa从headB开始走,pb也是一样,如此一来便能找到相交的节点,如果两个链表没有交点,pa和pb最终会同时指向空,最后返回两个指针的任意一个即可

2.环形链表

    题目链接:环形链表icon-default.png?t=N7T8https://leetcode.cn/problems/linked-list-cycle/description/     

先看代码:

typedef struct ListNode ListNode;
bool hasCycle(struct ListNode* head) {

    ListNode* fast = head;
    ListNode* slow = head;
    while (fast && fast->next) {
        slow = slow->next;
        fast = fast->next->next;
        if (slow == fast) {
            return true;
        }
    }
    return false;
}

 

思路:

  1. 快慢指针,先定义两个指针slow和fast,slow每次走一步,fast每次走两步,两个指针必然会在环中相遇
  2. 推导:进环前需要走N步,环的周长为M,那么slow进环时两者所走步数为slow=N,fast=2N,以链表next指针所指的方向为正方向那么就是slow领先M-N步,每次循环flow会相对于slow前进一步,M-N肯定是正整数,所以两个指针一定会在环中相遇。
  3. 温馨提示:如果是fast每次循环相对于slow前进的步数大于1就不一定相遇了,大家下去自己推导吧!

3.环形链表2

题目链接:环形链表2icon-default.png?t=N7T8https://leetcode.cn/problems/linked-list-cycle-ii/description/

 先看代码

typedef struct ListNode ListNode;
struct ListNode* detectCycle(struct ListNode* head) {
    ListNode* p1 = head;
    ListNode* p2 = head;
    while(p1&&p1->next){
        p1=p1->next->next;
        p2=p2->next;
        if(p1==p2){
            p1=head;
            while(p1!=p2){
                p1=p1->next;
                p2=p2->next;
            }
            return p1;
        }
    }
    return NULL;
}

 

思路:

        和上面的快慢指针一样,我们依然使用快慢指针:

  1. 如果存在环,两个指针会在环内相遇
  2. 两个指针相遇后,将其中一个指针重新指向头节点,随后每个指针都走一步,相遇处即为环的入口节点
  3. 推导,已知相遇时p1一定比p2多走一个环的距离,设p2走了T步后与p1相遇,进环前链表节点数为N,环长为M,有以下等式:

        (1)T=N+X;(2)2T=N+X+M;(1)-(2)得M=N+X;此时p2已经在环中走了X步,只需再走N步就可到达入环节点,而入环前的节点数恰好时N,故两个指针最后相遇的节点就是入环节点

这道题也可以在两个指针相遇后,将环从相遇处裁开,形成两个相交链表, 按照相交链表的方法来做,这里不再多说啦,大家自己下去实践吧

        

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值