两两交换链表中的节点 , 删除链表的倒数第N个节点 , 环形链表II

 

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

给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。

你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。

 

 

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode * dummyhead = new ListNode();
        dummyhead -> next = head;
        ListNode *cur = dummyhead;
        while ( cur -> next != nullptr && cur -> next -> next != nullptr ) {
            ListNode * tem = cur -> next;   //tem 指向 1
            ListNode * tem0 = cur -> next -> next -> next ;  // temp0 指向3
            cur -> next = cur -> next -> next;   //  将 0 下一个成 2
            cur -> next -> next = tem;   // 将2 的下一个 变为 1
            tem -> next =  tem0;  // 将 1 的下个一个变为 3
            cur  = cur -> next -> next;
        }
        return dummyhead -> next;

    }
};

 

 本题关键要注意不要断链 , 想好 链接顺序。

从虚拟头节点开始 处理 头节点 以后的 两个 换位, 之后cur指针指向  下两个要换位的 前一个(即 为 值为2 的节点) 

ps  在while循环中的  结束条件  可以理解为   要处理的是指针之后的两个 节点 所以 两节点 都不能为 空

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

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5] 

输入:head = [1], n = 1 输出:[]

输入:head = [1,2], n = 1 输出:[1]

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode *dummyhead = new ListNode(0);
        dummyhead -> next = head;
        ListNode *fast = dummyhead;
        ListNode *slow = dummyhead;
        while ( n-- && fast != nullptr ) {
            fast = fast -> next;
        }
        while ( fast -> next != nullptr ) {
            fast = fast -> next;
            slow = slow -> next;
        }
        slow -> next = slow -> next -> next;
        return dummyhead -> next;
    }
};

本题关键是  找到 要删除 节点的前一个 。 采用快慢指针 

 先让 快指针 走 n 个  之后  让快慢指针 一起走  直到 快指针的下一个 为空  (这等价与 让快指针 先走 n +1个之后快慢 一起走 直到 快指针为空 ) 当前快指针就为  所要处理 的元素 的 前一个 之后 删除就 行

3.环形链表II

 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

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 * cur = head ;
                ListNode * cur1 = fast;
                while ( cur != cur1 ) {
                    cur = cur -> next;
                    cur1 = cur1 -> next;
                }
                return cur;
            }
        }
        return NULL;
    }
};

判断 是否 有 环  采用 两个有差速 的指针 如果 相遇 即为有环 。

环的入口  采用 数学方式 推理 可以 得知   当 一个指针 从 头 走 , 一个指针从 两指针相遇的地方 往前 走  , 相遇的 地方 即为 入口。

 fast 速度 为2  ,slow 速度 为 1  所以 fast 走的路程 是slow 的二倍 

 即 (x + y ) * 2 = x + y + n*(y + z ) 化简 的 x = n * ( x + z ) - y

 再化为   x = (n - 1) *(x + y) + z;  

 由于 x + y 是一圈 所以 入口 与 其无关  最后可得 x = z 时 就是入口

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值