Day04链表2

链表Part02

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

struct ListNode* swapPairs(struct ListNode* head) {
    struct ListNode dummyNode ;
    dummyNode.next = head;
    struct ListNode *temp = &dummyNode;
    while(temp->next!=NULL&&temp->next->next!=NULL){
        struct ListNode *node1=temp->next;
        struct ListNode *node2=temp->next->next;
        temp->next = node2;
        node1->next=node2->next;
        node2->next=node1;
        temp = node1;
    }
    return dummyNode.next;
}

使用迭代的方法实现两两交换链表中的节点,创建了一个虚拟节点。

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

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* removeNthFromEnd(struct ListNode* head, int n) {
        struct ListNode dummyNode;
    dummyNode.next = head;
    struct ListNode *slow=&dummyNode,*fast=&dummyNode;
    for(int i = 0;i<=n;i++){
        fast = fast->next;
    }
    while(fast!=NULL){
        fast=fast->next;
        slow=slow->next;
    }
    struct ListNode *temp = slow->next;
    slow->next = temp->next;
    free(temp);
    return dummyNode.next;
}

使用快慢指针来解决,并设置一个虚拟节点,在题目中保证需要删除的节点下标小于链表大小的情况下,减少了判断次数。(虚拟节点确实好用,链表的头结点不是空无用处)

面试02.07.链表相交

采用双指针解决,设链表A的长度为a+c=m,链表B的长度为b+c=n,pA和pB一起移动,存在几种情形

  • 两个链表有交点
    • 若m=n,则两个指针共同移动到交点处停止,返回其中一个指针
    • 若m!=n,则两个指针到达链表末尾后,分别指向对方链表的头节点,最后共同达到交点处,pA移动次数为a+c+b,pB移动次数为b+c+a,返回其中一个指针】
  • 两个链表没有交点
    • 若m=n,两个指针同时移动到链表末尾,均指向NULL,返回NULL
    • 若m!=n,两个指针在移动m+n次后指向链表末尾,均指向NULL,返回NULL
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    if(headA==NULL||headB==NULL) return NULL;
    struct ListNode *pA=headA,*pB=headB;
    while(pA!=pB){
        pA= pA==NULL?headB:pA->next;
        pB= pB==NULL?headA:pB->next;
    }
    return pA;
}

142.环形链表ii

struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *fast=head,*slow=head;
    while(true){
        if(fast==NULL||fast->next==NULL) return NULL;
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast) break;
    }

    fast = head;
    while(fast!=slow){
        fast=fast->next;
        slow=slow->next;
    }

    return slow;
}

采用快慢指针fastslow指向链表头部head,令fast每轮走2步,slow每轮走1步,执行后有以下情形(设链表中非环的部分长度为a,环的部分长度为b):

  • fast指针到达过链表末端,说明链表无环,此时直接返回null。如果链表存在环,则双指针一定会相遇。
  • fast=slow时,两指针在环中第一次相遇,设两个指针分别走了x,y步,则x=2yfastslow多走了n倍的环的长度,环的长度为b,则x=y+nb ,两个式子相减得y=2nbx=nb,此时,我们可以计算出到达入口处需要走a+nb步,则slow指针再走a步即可到达入口点,我们将fast指针指向头节点,和slow一同向后移动,经过a步后,移动到入口节点处,返回该节点

采用该种方式解决问题需要数学知识的应用,时间复杂度为O(n),空间复杂度为O(1)

采用哈希表的方式空间复杂度较高,不过思路要简单许多,二刷时采用两种方式都做一遍。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值