代码随想录算法训练营day4 | leetcode P24 交换链表中的节点、leetcode P19 删除列表中的倒数第n个节点、leetcode 面试题02.07 、leetcode P142

P24 两两交换链表中的节点

代码随想录讲解

思路:

定义中间变量进行交换就好

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dyummhead = new ListNode(0);
        dyummhead->next = head;
        ListNode* cur = dyummhead;
        while(cur->next !=nullptr &&cur->next->next !=nullptr){
            ListNode* tmp =cur->next;
            ListNode* tmp1 = cur->next->next->next;//
            cur->next = cur->next->next;
            cur->next->next = tmp;
            cur->next->next->next = tmp1;
            cur = cur->next->next;
        }
        return dyummhead->next;
    }
};

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

代码随想录讲解

思路:

定义fast指针和slow指针,初始值为虚拟头结点,  fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),fast和slow同时移动,直到fast指向末尾,删除slow指向的下一个节点。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dyummhead = new ListNode(0);
        dyummhead->next = head;
        ListNode* fast = dyummhead;//
        ListNode* slow = dyummhead;//
        
        while(n && fast !=NULL){
            fast = fast->next;
            n--;
        }
        fast = fast->next;//
        while(fast !=NULL){
            fast=fast->next;
            slow=slow->next;
        }
        slow->next = slow->next->next;
        return dyummhead->next;
    }
};

面试题02.07 链表相交

代码随想录讲解

思路:

注意点:指针相同不是值相同,而是指针的地址相同。

两个链表相交,那么从交点开始两个链表后面的部分都相同。那么我们可以把两个链表的尾部对齐,将长链表的指针移动到较短指针开始的位置

然后再遍历链表A和链表B,找到相等的节点即可

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *answer = NULL;
        int lenA = 0,lenB = 0;
        ListNode *curA = headA;
        ListNode *curB = headB;
        while(curA !=NULL){
            lenA ++;
            curA = curA->next;
        }
        while(curB !=NULL){
            lenB++;
            curB = curB->next;
        }
        curA =headA;
        curB = headB;
        int gap;
        if(lenA>lenB){
            gap = lenA - lenB;
            while(gap){
                curA = curA->next;
                gap--;
            }
        }else if(lenA <lenB){
            gap = lenB - lenA;
            while(gap){
                curB = curB->next;
                gap--;
            }
        }else{
            gap = 0;
        }
        while(curA!=NULL &&curB !=NULL){
            if(curA == curB){
                answer = curA;
                break;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return answer;
    }
};

P142 环形链表||

代码随想录讲解

思路:

1.如何判断链表是否有环:

利用双指针,定一个一快慢指针,其中快指针一次移动两个节点,慢指针一次移动一个节点,因为快指针的移动速度是慢指针移动速度的两倍,那么在经过环的时候,在慢指针在环内转了一圈之前,快慢指针必然会相遇一次。若快慢指针相遇,则可以证明该链表存在环。

2.如何找到该环的入口:

在相遇节点和头节点处各定义一个指针,指针相遇的地方必然是该环的路口。原因:

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

那么相遇时: slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。根据公式,则环的入口x必然等于转的圈数-1加上z,那么可以定义一个指针meet在相遇节点上,定义一个catcher节点在头结点上,然后让两个指针同时出发,他们相遇的节点就是环的入口。

代码:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
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(fast == slow){
                ListNode *meet = fast;
                ListNode *catcher = head;
                while(meet != catcher){
                    meet = meet->next;
                    catcher = catcher->next;
                }
                return catcher;
                break;
            }
            
        }
        return NULL;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值