Day4| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点, 面试题 02.07. 链表相交, 142.环形链表II

Day4| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个节点, 面试题 02.07. 链表相交, 142.环形链表II

两两交换链表中的节点

LeetCode题目链接:https://leetcode.cn/problems/remove-linked-list-elements/

解题思路

  先看题目,因为是要两两进行交换,所以与直接翻转有所不同。需要考虑更多的情况,比如头结点的更换问题。为了避免特殊处理,添加虚拟头结点。之后,因为两两反转后,指向第三个节点的部分也出现了改变,因此第三个节点也需要用额外的临时变量进行存储。

  因此,首先初始化一个虚拟头结点来作为当前的头结点,再补充一个临时变量,进行迭代。

  代码如下:

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head==NULL||head->next==NULL){
            return head;
        }
        ListNode *dummyHead = new ListNode(0,head);
        ListNode *front = dummyHead;
        ListNode *pred =head;
        ListNode *temp;
        while(front->next!=NULL&&front->next->next!=NULL){
            temp = pred->next->next;
            pred->next->next = pred;
            front->next = pred->next;
            pred->next = temp;
            front = pred;
            pred  = front->next;
        }
        return dummyHead->next;
    }
};

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

LeetCode题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list

解题思路

  删去倒数第n个元素,那么首先要知道整个链表的长度,在已知链表长度的基础上,可以得出倒数第n个值是正数的第几个节点。

  此后,设置一个节点用于到达该位置,另一个节点集合该位置之前的点。便完成了删除节点的操作。

  具体代码如下:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummyHead = new ListNode(0,head);
        ListNode *current = head;
        ListNode *front = dummyHead;
        int size = 0;
        while(current!=NULL){
            current = current->next;
            size++;
        }
        current = head;
        for(int i=0;i<size-n;i++){
            current = current->next;
            front = front->next;
        }
        front->next = current->next;
        return dummyHead->next;
    }
};

链表相交

LeetCode题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

解题思路

  需要判定两个链表的相交部分,主要需要保持两个链表的节点更新始终保持到尾部的距离相同。这样才能同步去判定节点位置是否相交。但是因为两个链表长度不定,因此需要先计算出链表的长度。再使长度不等的链表中较长的链表去除头部元素,使其到尾部节点的距离相同,再进行迭代,就可以轻松判定出是否相交了。

具体代码如下:

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* currentA = headA;
        ListNode* currentB = headB;
        int sizeA=0,sizeB=0;
        while(currentA!=NULL){
            currentA = currentA->next;
            sizeA++;
        }
        while(currentB!=NULL){
            currentB = currentB->next;
            sizeB++;
        }
        currentA = headA;
        currentB = headB;
        if(sizeA<sizeB){
            swap(sizeA,sizeB);
            swap(currentA,currentB);
        }
        int dif = sizeA-sizeB;
        for(int i=0;i<dif;i++){
            currentA = currentA->next;
        }
        while(currentA!=NULL){
            if(currentA==currentB){
                return currentA;
            }
            currentA = currentA->next;
            currentB = currentB->next;
        }
        return NULL;
    }
};

环形链表II

LeetCode题目链接:https://leetcode.cn/problems/linked-list-cycle-ii

解题思路

  先看题目,首先需要判断链表是否有环,因此可以进行判断,一旦指针在迭代时出现->next=NULL则说明不存在环形,跳出循环并返回NULL。

  之后进行环形判断,当链表存在环形,易得快慢指针一定存在交点。假设从链表起点到环形起点的距离为 x x x,环形起点到交点的距离为 y y y,交点到环形起点的距离为 z z z。可以得到以下公式:

当快慢指针相遇时有,其中 ( x + y ) (x+y) (x+y)为慢指针的移动距离,由于快指针是慢指针的二倍,所以乘以2后等式成立:
2 ( x + y ) = x + y + n ∗ ( y + z ) 2(x + y) = x +y +n*(y+z) 2(x+y)=x+y+n(y+z)

化简可以得到:
x + y = n ∗ ( y + z ) x+y = n*(y+z) x+y=n(y+z)

即可以求得链表起点到环形起点的距离公式,如果得到 x x x即可得出环形的起点位置:
x = ( n − 1 ) ∗ ( y + z ) + z x = (n-1)*(y+z) + z x=(n1)(y+z)+z

同时,可以观察到 y + z y+z y+z为一个环形,因此可以看作:从交点位置出发,与从链表头出发,一定会在环形的起点处相遇。

  代码如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head;
        ListNode *slow = head;
        while(fast!=NULL&&fast->next!=NULL){
            fast = fast->next->next;
            slow = slow->next;
            if(slow==fast){
                ListNode * index1=head;
                ListNode * index2=slow;
                while(index1!=index2){
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;

            }
        }
        return NULL;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值