打卡第四天|力扣 24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点 、 面试题 02.07. 链表相交 、142.环形链表II 。

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

题目链接24. 两两交换链表中的节点

这道题还是用虚拟头结点的方式简单一点

首先我们判断终止条件,如果是偶数,则下一个是空指针停止,如果是奇数,则下一个的下一个指针为空停止

while(cur->next &&cur->next->next )

要注意cur->next要现在前面,二者不可以调换,因为&&优先级从左往右,会在偶数时造成空指针报错

然后注意交换顺序,先保存节点1,3的地址

我们dummyhead->next = head; cur=dummyhead;

因为只有知道要交换的两个节点的前一个节点,我们才能对要交换的两个节点进行操作,这就是链表的特点

红色为第一步,让dummyhead指向节点2

绿色为第二步,让节点2指向节点1

黄色为第三步,让节点1指向节点3

至此,这一串就交换好了,链表为dummyhead->2->1->3

/**
 * 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) {
//虚拟头节点指向head
    ListNode* dummyhead = new ListNode(0);
    dummyhead->next = head;
//auto == ListNode*
    auto cur = dummyhead;
    while(cur->next &&cur->next->next ){
//保存1节点地址
        auto temp1 = cur->next;
//保存3节点地址
        auto temp2 = cur->next->next->next;
//交换
        cur->next = cur->next->next;
        cur->next->next = temp1;
        temp1->next =temp2;
        cur = cur->next->next;
    }
    return dummyhead->next;
    }
};

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

题目链接如下

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

这道题使用两个指针可以很方便的做出来,首先,我们要删除倒数第n个节点,我们必须操作倒数第n+1个节点

我们先创建一个虚拟头节点,让两个指针都等于虚拟头节点,快指针先移动n+1次,之后快慢指针一起移动,直到快指针为空的位置,这时慢指针的位置就位于倒数n+1的位置了

 完整代码如下:

/**
 * 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* dummyhead = new ListNode(0);
    dummyhead->next = head;
//两个指针
    auto fast = dummyhead;
    auto slow = dummyhead;
    n += 1;
//判断特殊情况
     if(!head | !head -> next) return NULL;
//先动快指针
    while(n--){
        fast = fast->next;
    }
//一起移动
    while(fast != NULL){
        fast = fast->next;
        slow = slow->next;
    }
//删除操作
    slow->next = slow->next->next;
//有可能删除的是原头节点,所以我们返回的应该是虚拟头节点的next
    return dummyhead->next;
    }
};

02.07. 链表相交

题目链接面试题 02.07. 链表相交

这道题也是双指针解法

用两个指针分别在两个链表开头开始走,如果一个指针走到null了,也就是走到头了,就再从另一个链表的开头开始走,这样,两个指针最后相遇的地方就会是第一个公共交点。

画的不太好,语言描述太乏力了

 

 

 

 具体实现到代码如下:p,q就是两个指针

class Solution {
public:
    ListNode *findFirstCommonNode(ListNode *headA, ListNode *headB) {
       auto p=headA,q=headB;
       while(p!=q){
           if(p)p=p->next;
           else p=headB;
           if(q)q=q->next;
           else q=headA;
       }
       return q;
    } 
     
    
};

142.环形链表II 

题目链接如下:

​​​​​​142. 环形链表 II

快指针每次走两步,慢指针每次走一步,如果它们相遇了,则证明是环形

核心是通过数学推出,从两指针相遇节点出发和从头节点出发,到环形入口节点的距离相同

我的理解是,进入环的距离假设为X,快指针相对与慢指针的相对速度为1,所以它们相遇时的追赶距离就是Z这段路上快指针对慢指针的相对位移

 

/**
 * 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) {
        auto fast = head;
        auto slow = head;
        while(fast != NULL && fast->next != NULL){
/fast每次走两步 slow每次走一步
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow){
//从相遇点开始
                auto tmp1 = head;
                auto tmp2 = fast;
                while(tmp1 != tmp2){
                    tmp1 = tmp1->next;
                    tmp2 = tmp2->next;
                }
//相交处既是环形入口
                return tmp1;
            }
        }
//不是环形则返回空
        return NULL;
    }
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr丶锤子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值