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

24. 两两交换链表中的节点

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

使用双指针+虚拟头结点,成功ac。

struct ListNode* swapPairs(struct ListNode* head) {
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    struct ListNode* p = head, *pre = dummyHead;
    while(p != NULL && p->next != NULL){
        pre->next = p->next;
        p->next = pre->next->next;
        pre->next->next = p;
        pre = p;
        p = p->next;
    }
    return dummyHead->next;
}

19.删除链表的倒数第N个节点

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

可以算是“暴力解法”:首先遍历链表,求出链表长度,然后再寻找需要删除的位置,删除节点即可。使用了虚拟头结点。

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    int cnt = 0, i = 0;
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode)), *p = head, *temp = NULL;
    dummyHead -> next = head;
    while( p != NULL ){
        cnt++;
        p = p->next;
    }
    for(i = 0, p = dummyHead; i < cnt-n ; i++){
        p = p->next;
    }
    temp = p->next;
    p->next = p->next->next;
    free(temp);
    return dummyHead->next;
}

二、学习文章后收获

1.删除删除链表的倒数第N个节点:“快慢指针”经典应用

注意点:快指针比慢指针多走几步?(n+1)步。

struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
    struct ListNode* dummyHead = (struct ListNode*)malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    struct ListNode* fast = dummyHead, *slow = dummyHead;
    for(int i = 0; i <= n; i++){ //fast先走(n+1)步
        fast = fast->next;
    }
    
    while(fast != NULL){ //快慢指针一起向后移动
        fast = fast->next;
        slow = slow->next;
    }
    //删除节点
    fast = slow->next;
    slow->next = slow->next->next;
    free(fast);
    
    return dummyHead->next;
}

2.大胆用dummyHead吧,太好用了,literally

三、过程中遇到的问题

一开始写成了”快指针先走n步“,导致出现了访问空指针的报错。


面试题 02.07. 链表相交

题目链接:link
文章讲解:link

一、做题感受&第一想法

要看清楚题目:本题的交点是”指针值“相等,而不是“数值”val相等。
对“链表相交“的经典解法:让长链表先走几步,统一二者的剩余链表长度,再遍历,判断指针是否相等。

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    int lengthA = 0, lengthB = 0;
    struct ListNode *pa = headA, *pb = headB, *target = NULL;
    while(pa != NULL){ //求链表A的长度
        lengthA++;
        pa = pa->next;
    }
    while(pb != NULL){ //求链表B的长度
        lengthB++;
        pb = pb->next;
    }
    pa = headA; pb = headB;
    //让长链表先走几步,以统一剩余链表长度。
    if(lengthA > lengthB){ 
        for(int i = 0; i < lengthA - lengthB ; i++){
            pa = pa->next;
        }
    }
    if(lengthA < lengthB){
        for(int i = 0; i < lengthB - lengthA ; i++){
            pb = pb->next;
        }
    }
    //统一剩余长度后,pa和pb主簿后移,直到找到pa==pb的位置,即指针相等,链表相交。
    while(pa != NULL && pb != NULL){
        if(pa == pb && target == NULL){
            target = pa;
        }
        pa = pa->next;
        pb = pb->next;
    }
    return target;
}

142.环形链表II

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

没什么太好的思路。

二、学习文章后收获

1.思路

详见“文章讲解”。此处说明几个注意点:

  • 总体思路:①判断有无环:快慢指针,快指针每次后移两个,慢指针每次后移一个,如果相遇则有环,如果快指针到null了则无环。②寻找环入口:证明请看文章讲解。最终结论是,从快慢指针相遇点到环入口的距离,和从链表开头到环入口的距离,相等。
  • 注意无环时判断返回的条件:
    if((fast == NULL) || (fast->next == NULL)){
        return NULL;
    }

2.代码

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *slow = head, *fast = head, *meet = NULL;
    //【一:判断有无环】
    while( fast != NULL && fast->next != NULL ){
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast){
            break;
        }
    }
    if((fast == NULL) || (fast->next == NULL)){
        return NULL;
    }

    //【二:寻找环入口】
    slow = head;
    while( slow != fast ){
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}
  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值