代码随想录算法训练营第四天|24 两两交换链表中的节点、19 删除链表的倒数第n个节点、面试题02.07 链表相交、142 环形链表||

一、24 两两交换链表中的节点

//迭代版本  
struct ListNode* swapPairs(struct ListNode* head) { 
     //定义虚拟头节点
    struct ListNode* dummyhead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyhead->next = head;
    struct ListNode* cur = dummyhead;
    while(cur->next!=NULL&&cur->next->next!=NULL)
    {
        struct ListNode*tmp = cur->next;//保存节点1
        struct ListNode*p=cur->next->next->next;//保存节点3
        cur->next = cur->next->next;//cur->节点2
        cur->next->next = tmp;//节点2->节点1
        tmp->next=p;//节点1->节点3//完成第一次交换
        cur=cur->next->next;//cur走到节点1的位置
    }
    return dummyhead->next;
    
}
//递归版本
struct ListNode* swapPairs(struct ListNode* head) { 
     //结束调价:头节点为空或头结点的下一个为空
    if(head == NULL||head->next == NULL)
            return head;
    //创建一个节点指针类型保存头结点下一个节点
    struct ListNode*cur = head->next;
    //更改头结点+2位节点后的值,并将头结点的next指针指向这个更改过的list
    head->next = swapPairs(cur->next);
    //将新的头结点的next指针指向老的头节点
    cur->next = head;
    return cur;
}

在这里,小编还是建议大家先弄明白迭代版本,然后再理解递归版本!!!

二、19 删除链表的倒数第n个节点

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode*dummyhead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyhead->next = head;//创建了一个虚拟头节点
    struct ListNode*fast = dummyhead->next;//让快指针多走一步,慢指针就会停在n的前驱那里
    struct ListNode*slow = dummyhead;
    while(n--&&fast!=NULL)
    {
        fast = fast->next;
    }
    while(fast!=NULL)
    {
        fast = fast->next;
        slow = slow->next;
    }
    slow->next=slow->next->next;//删除操作
    return dummyhead->next;
}

在这道题里,大家一定要注意的是如何找到倒数第n个节点!要理解这种方法。

三、 面试题02.07 链表相交

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    struct ListNode *curA = headA;
    struct ListNode *curB = headB;
    int lenA = 0,lenB = 0;//链表A和B的长度
    for(curA = headA;curA!=NULL;curA=curA->next)
        lenA++;
    for(curB = headB;curB!=NULL;curB=curB->next)
        lenA++;
    //长度差
    int tmp;
    //计算长度差,让curA和lenA成为长链表的指针和长度
    if(lenA>lenB)
    {
        curA=headA;
        tmp = lenA-lenB;
    }
    else
    {
        curA = headB;
        tmp = lenB-lenA;
    }
    //对齐指针
    while(tmp--&&curA!=NULL)
        curA =curA->next;
    //找交点
    while(curA!=NULL)
    {
        if(curA==curB)//找到交点就return
            return curA;
        //没有找到继续向后移动
        curA = curA->next;
        curB= curB->next;
    }
    return NULL;//没有找到返回NULL;
}

这道题的思路是先定义两个指针指向两个链表的头节点,然后定义两个链表的长度,计算链表的长度以及长度差,将长链表的头节点和长度够设置为curA和lenA,然后将两个链表的指针对齐,这时就开始遍历进行比较了。当找到交点时,return curA;若没找到两个指针继续向后移动;若遍历结束还没找到,则return NULL。

四、142 环形链表||

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast = head;
    struct ListNode *slow = head;
    while(fast!=NULL&&fast->next!=NULL){
        fast = fast->next->next;
        slow=slow->next;
        //判断环
        if(fast == slow){
            //找环的入口
            struct ListNode *p = fast;
            struct ListNode *q = head;
            while(p!= q){
                p = p->next;
                q=q->next;
            }
            return p;//找到入口
        }
    }
    //不是环
    return NULL;
}

对于环形链表这道题来说,重点在于判断环和找到环的入口。

首先是判断环,定义两个指针分别为快指针和慢指针,快指针一次走两步,慢指针一次走一步,如果快慢指针相遇则链表有环。这里有朋友可能会担心快指针为什么不会跳过慢指针,因为快指针走两步,慢指针走一步相当于快指针比慢指针多走一步,这样就不会跳过慢指针。

接下来就是在判断有换的基础上找到环的入口。这里为了帮助大家理解,我准备了一个图片,大家可以学习图片自行模拟!

在搞清楚环这个等式之后,有的朋友可能会想,为什么快慢指针不能在第一圈就相遇呢?

还是用图来解决,这里的图使我们把换展开之后的样子,没有上图的x部分,大家不要弄混了!

好啦,这就是今天博客的全部内容,感谢大家的观看啦!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值