leetcode链表题目练习(续)

本文介绍了如何解决LeetCode中的四个链表问题:两两交换节点、删除链表的倒数第n个节点、查找链表相交点以及检测环形链表。作者分享了代码实现和关键策略,包括使用虚拟头节点、双指针技巧和快慢指针法。
摘要由CSDN通过智能技术生成

leetcode链表题目练习(续)

1. 两两交换链表节点

两两交换的链表节点的注意事项:

  • 交换的是节点不是值
  • 要注意第一个节点的情况
  • 定义一个虚拟头节点会更方便操作

我做错的原因:

  • 节点的next少打了一个,导致指针乱指

代码如下:

/**
 * 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 *dummyhead =new ListNode(0);
        ListNode *cur = dummyhead;
        dummyhead->next = head;
        while (cur->next != nullptr && cur->next->next != nullptr){
            ListNode *tem = cur;
            ListNode *tem1 = cur->next->next->next;
            cur = cur->next->next;
            cur->next = tem->next;
            tem->next = cur;
            cur->next->next = tem1;
            cur = cur->next;
            tem = nullptr;
            tem1 = nullptr;
        }
        return dummyhead->next;

    }
};

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

思路:怎么先找到倒数第n个节点

  • 思路第一条:一前一后双指针一格一格先到end再往后移动
    不可行
  • 思路第二条:
    先把快指针和慢指针拉开n+1个距离
    等快指针为NULL的时候就可以确定要删去节点的位置了

第二种方法我认为比较巧妙因为它相当于先将尺子长度固定再放上去量取,我们平时做题既要想到一前一后连着造短尺子一段一段量取也要想着直接固定长度再量取

代码如下:

/**
 * 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);
        ListNode* cur = head;
        ListNode* pre = dummyhead;
        dummyhead->next = head;
        int size = 0;
        while (pre->next != nullptr) {
            pre = pre->next;
            size++;
        }
        int location = size - n;
        pre = dummyhead;
        while (location--) {
            cur = cur->next;
            pre = pre->next;
        }
        pre->next = cur->next;
        delete cur;
        return dummyhead->next;
    }
};

3. 链表相交

相交其实就是找两段他们开始相同的那个节点(注意不是val)
这个肯定要用到遍历,这是无法躲掉的,但是两段for循环是否有点笨拙?
解决方法:长链表的前几个元素肯定不能是相交的部分,不然不可能后面的节点一样
具体方案:

  • int lane1
  • int lane2
  • gap = lane1 - lane2(注意要先把长的变成lane1)
  • 进行遍历操作找交点
    具体代码如下:
/**
 * 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* cur1 = headA;
        ListNode* cur2 = headB;
        int lineA = 0;
        int lineB = 0;
        while (cur1 != nullptr){
            cur1 = cur1->next;
            lineA++;
        }
        while (cur2 != nullptr){
            cur2 = cur2->next;
            lineB++;
        }
        cur1 = headA;
        cur2 = headB;
        if (lineB > lineA){
            swap(cur1,cur2);
            swap(lineA,lineB);
        }
        int n =lineA - lineB;
        while (n--){
            cur1 = cur1->next;
        }
        while (lineB--){
            if(cur1 == cur2){
                return cur1;
            }
            cur1 = cur1->next;
            cur2 = cur2->next;
        }
        return NULL;
    }
};

4. 环形链表

这道题是我遇到链表里面最难的题目
首先这道题有两个难点

  1. 这是不是环形链表
  2. 这个环形链表的开始在哪里
    这两问一个比一个难,首先判断是不是环形链表
    可以用快慢指针判断,也就是说如果是环形链表那么快指针一定会绕着跑从后面追上慢指针从而判断是环形链表。
    也就是慢指针的距离=x+y
    快指针的运动距离=x+(y+z)*n
    y+z是一圈的距离
    从而判断是否是个环形链表
    同时根据快慢指针可以知道:
    慢指针的距离是快指针的二分之一
    也就是:2(x+y)=x+(y+z)*n
    那么不难得出:x = (n - 1) (y + z) + z
    因为y+z是一圈的距离那么可以得出:z=x
    那么这道题也就解完了,代码并不难,主要难在算法的设计
    代码如下:
/**
 * 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;
        ListNode* index;
        ListNode* index1 = head;
        while (fast != NULL && fast->next != NULL){
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow){
                index = fast;
                while (index != index1){
                    index = index->next;
                    index1 = index1->next;
                }
                return index1;
            }
        }
        return NULL;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值