首页 > 其他分享 >链表part02

链表part02

时间:2024-08-04 19:08:40浏览次数:17  
标签:slow ListNode part02 fast next 链表 节点

今天是8月3日,学习了链表的第二部分。

  1. 交换链表两个节点,考察对next的操作和tmp的灵活运用。
  2. 删除链表的倒数第N个节点,双指针减少遍历次数。
  3. 链表相交,移动链表尾对齐,其实就是动长链表的指针。
  4. 环形链表,记住方法。

4. 24交换链表两个节点

题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。


交换节点比上一道更明显,需要更改原始列表中的节点的next。那么需要合理设置指针+更换next的顺序+及时存储tmp

  1. 注意指针指的位置:比如节点1->2->3,那么cur指向1,可以操作2和3的next。
ListNode* swapPairs(ListNode* head) {
    ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
    dummyHead->next = head; 
    ListNode* cur = dummyHead;
    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; // cur移动两位,准备下一轮交换
    }
    ListNode* result = dummyHead->next;
    delete dummyHead;
    return result;
}

5. 19删除链表的倒数第N个节点(双指针)

题目:删除链表的倒数第 n 个结点,并且返回链表的头结点。


链表只可以从前往后挨个遍历,想要一遍解决问题常用双指针。删除倒数第n个,只需要让fast早走n步,然后fast和slow同步走,fast走到末尾时,slow->next就是要被删除的节点。

要删除某个点,slow需要指着这个点的上一个节点,才可以做到删除。

ListNode* removeNthFromEnd(ListNode* head, int n) {
    // 虚拟头节点 
    ListNode* dummyhead = new ListNode(0);
    dummyhead->next=head;
	//快慢指针
    ListNode* fast = dummyhead;
    ListNode* slow = dummyhead;
	//先动fast指针
    while(fast->next!=nullptr){//保证动fast时不出界
        if(n>0){
            n--;
            fast=fast->next;
        }   
        else
            break; 
    }
	//fast和slow同时动,直到fast到达最后一个节点停止
    while(fast->next!=nullptr){
        fast=fast->next;
        slow=slow->next;
    }
    // ListNode *tmp = slow->next;  C++释放内存的逻辑
    // slow->next = tmp->next;
    // delete tmp;
    slow->next=slow->next->next;
    return dummyhead->next;
}

6. 链表相交(移动链表尾对齐)

题目:两个单链表的头节点 headAheadB ,找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null


求两个链表交点节点的指针。最普通的想法,两个for嵌套,但是考虑相交的特点,相交点后面的都一样,所以:

  1. 求出两个链表的长度,并求出两个链表长度的差值,然后让两个链表末尾对齐的位置。
  2. 此时比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。
  3. 否则循环退出返回空指针。
  1. 交点不是数值相等,而是指针相等。
  2. 链表尾对齐,其实就是curA移动到中间,剩下的A链表和B一样长。
 ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
     ListNode* curA = headA;
     ListNode* curB = headB;
     int lenA = 0, lenB = 0;
     while (curA != NULL) { // 求链表A的长度
         lenA++;
         curA = curA->next;
     }
     while (curB != NULL) { // 求链表B的长度
         lenB++;
         curB = curB->next;
     }
     curA = headA;
     curB = headB;
     // 让curA为最长链表的头,lenA为其长度
     if (lenB > lenA) {
         swap (lenA, lenB);
         swap (curA, curB);
     }
     // 求长度差
     int gap = lenA - lenB;
     // 让curA和curB在同一起点上(末尾位置对齐)
     while (gap--) {
         curA = curA->next;
     }
     // 遍历curA 和 curB,遇到相同则直接返回
     while (curA != NULL) {
         if (curA == curB) {
             return curA;
         }
         curA = curA->next;
         curB = curB->next;
     }
     return NULL;
 }

7. 142环形链表

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


a. 如何判定是否有环?

快慢指针法,定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

  • fast指针一定先进入环中,如果fast指针和slow指针相遇的话,一定是在环中相遇。
  • 相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

b. 如何判断环的起始点?

那么相遇时: 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 - 1) A + z

因此,发现从相遇点到入环点的距离z加上 n−1 圈的环长,恰好等于从链表头部到入环点的距离x。

因此,当发现 slow 与 fast 相遇时,再额外使用一个指针 ptr。起始,它指向链表头部;随后,它和 slow 每次向后移动一个位置。最终,它们会在入环点相遇。

ListNode *detectCycle(ListNode *head) {
    ListNode* fast = head;
    ListNode* slow = head;
    while(fast != NULL && fast->next != NULL) {
        slow = slow->next;
        fast = fast->next->next;
        // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
        if (slow == fast) {
            ListNode* index1 = fast;
            ListNode* index2 = head;
            while (index1 != index2) {
                index1 = index1->next;
                index2 = index2->next;
            }
            return index2; // 返回环的入口
        }
    }
    return NULL;
}

今日古诗

西江月·日日深杯酒满
朱敦儒〔宋代〕

日日深杯酒满,朝朝小圃花开。自歌自舞自开怀,无拘无束无碍。
青史几番春梦,黄泉多少奇才。不须计较与安排,领取而今现在。

上片起首写出词人终日醉饮花前的生活。深杯酒满见得饮兴之酣畅,小圃花开点出居处之雅致。无一字及人,而人的精神风貌已隐然可见。后二句则直陈快乐自由的情态;
下片文情陡变,两个对句表达了词人对世事人生的认识,末句是对上片所描述闲逸自得生活之底蕴的概括和揭示。全词用语浅自而意味悠远,清新淡雅,韵味天成,语意俱佳,流露出一种闲旷的情调

标签:slow,ListNode,part02,fast,next,链表,节点
From: https://www.cnblogs.com/yuehuaicnblogs/p/18342078

相关文章

  • 数据结构:链表经典算法OJ题
    目录前言一、移除链表元素二、反转链表三、合并两个有序链表四、链表的中间节点五、环形链表的约瑟夫问题前言  在了解了链表的相关知识后,我们还需要一些题目进行练习加深对链表这方面知识的理解,也可以用来检测链表这块学的的怎么样,废话不多说,开始上手。一、移......
  • 算法题之旋转链表
    旋转链表给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。示例1:输入:head=[1,2,3,4,5],k=2输出:[4,5,1,2,3]示例2:输入:head=[0,1,2],k=4输出:[2,0,1]提示:链表中节点的数目在范围 [0,500] 内-100<=Node.val<=1000<=k<=......
  • 代码随想录算法训练营day03|203.移除链表元素,707.设计链表,206.反转链表
    203.移除链表元素题目链接:https://leetcode.cn/problems/remove-linked-list-elements/description/我的代码(分头节点和中间节点两种情况操作):/***Definitionforsingly-linkedlist.*structListNode{*intval;*ListNode*next;*ListNode():val......
  • Linux内核-内核链表
    1内核链表内核链表本质就是一个双向循环链表:链表的实现仅用一个include/linux/list.h实现。内核链表有别于传统链表就在节点本身不包含数据域,只包含指针域。故而可以很灵活的拓展数据结构。使用时包含在用户数据结构内部。1.1内核链表结构体structlist_head{struct......
  • leetcode 021:删除链表的倒数第 N 个结点
    LCR021.删除链表的倒数第N个结点给定一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。示例1:输入:head=[1,2,3,4,5],n=2输出:[1,2,3,5]示例2:输入:head=[1],n=1输出:[]示例3:输入:head=[1,2],n=1输出:[1]structListNode*removeNthF......
  • C++实现静态链表
    #include<iostream>usingnamespacestd;//定义静态链表的最大容量constintMAX_SIZE=100;//节点类classNode{public:intdata;//节点存储的数据intnext;//节点指向下一个节点的索引(在数组中的位置)//默认构造函数Node():data(0......
  • 链表part01
    今天是8月2日,学习了链表的基础知识。题目主要是链表的基础操作和反转链表,注意虚拟头节点的使用、next的顺序和tmp的灵活使用。1.移除元素题目:给一个链表的头节点head和整数val,请删除链表中所有满足Node.val==val的节点,并返回新的头节点。删除的方法,cur指针挨个遍......
  • 结构体与共用体,链表的学习
    结构体定义        C语言允许用户自己定义一种数据结构,称为结构体。        声明一个结构体类型一般形式为:                strcut 结构体名                {                    成员列表......
  • 141.环形链表
    给你一个链表的头节点 head ,判断链表中是否有环。如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从0开始)。注意:pos 不作为参数进行传递 。仅仅是为......
  • LeetCode | 单链表操作
    LeetCode203移除链表元素LeetCode707设计链表LeetCode206反转链表主类ListNodepackagecom.github.dolphinmind.linkedlist.uitls;/***@authordolphinmind*@ClassNameListNode*@description*@date2024/8/3*///链表组成元素:节点publicclass......