代码随想录算法训练营day4,链表,如何求含环形链表的入环第一个结点?

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

题解

    ListNode* swapPairs(ListNode* head) {
        ListNode *dumyhead = new ListNode(0, head);
        ListNode *cur = dumyhead;
        ListNode *temp = nullptr;
        ListNode *temp1 = nullptr;
        while (cur->next && cur->next->next) {
            temp = cur->next;
            cur->next = cur->next->next;
            temp1 = cur->next->next;
            cur->next->next = temp;
            temp->next = temp1;
            cur = cur->next->next;
        }
        head = dumyhead->next;
        delete dumyhead;
        return head;
    }

总结

        依旧引入虚拟头结点保证操作统一,另外注意改变链表结点指向时,提前保存下一次循环需要的结点指针。

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

题解

    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dumyhead = new ListNode(0, head);
        ListNode *fast = dumyhead;
        ListNode *slow = dumyhead;
        int count = n + 1;
        while (count--) fast = fast->next;
        while (fast) {
            fast = fast->next;
            slow = slow->next;
        }
        ListNode *temp = slow->next;
        slow->next = slow->next->next;
        delete temp;
        head = dumyhead->next;
        delete dumyhead;
        return head;
    }

总结

        双指针法,fast先走n步后slow指针出发,然后fast指空时,slow指向需要被删除的结点。

02.07.链表相交

题解

    int get_length(ListNode *head) {
        if (!head) return 0;
        int count = 0;
        ListNode *cur = head;
        while (cur) {
            cur = cur->next;
            count++;
        }
        return count;
    }
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        if (headA == nullptr || headB == nullptr) return nullptr;
        ListNode *dumyhead1 = new ListNode(0, headA);
        ListNode *dumyhead2 = new ListNode(0, headB);
        int A_length = get_length(headA);
        int B_length = get_length(headB);
        int cap = abs(A_length - B_length);
        ListNode *first_move = (A_length >= B_length)? dumyhead1: dumyhead2;
        ListNode *second_move = (first_move == dumyhead1)? dumyhead2: dumyhead1;
        while (cap--) first_move = first_move->next;
        while (first_move && first_move->next != second_move->next) {
            first_move = first_move->next;
            second_move = second_move->next;
        }
        return first_move->next;
    }

总结

        将两个链表各遍历一次,获得两个链表的长度,然后让first指向更长的链表头结点,让其先开始移动,将长度差消除,此时first指针跟second指针对齐以后,开始循环判断是否指向头一个结点,如果指向同一个结点,则为交点结点。

142.环形链表二

题解

   ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head;
        ListNode *slow = head;
        while (fast && fast->next) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                ListNode *index1 = fast;
                ListNode *index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;
            }
        }
        return nullptr;
    }

总结

        算法背后的数学原理还没有搞清楚,先背下来这种算法吧。后面再花时间理解一下数学原理。

链表总结

        1.虚拟头结点可以方便链表统一操作,我不使用虚拟头结点,算法总是对只含一个结点的case ac不了,很烦。

        2.双指针法在链表这里也挺好用的,但要搞懂指针指向的含义,指针更新的逻辑。

        3.其实408统考算法题出过跟19题一模一样的题目。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值