IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 、 19.删除链表的倒数第N个节点 、面试题 02.07. 链表相交 、142.环形链表II -> 正文阅读

[数据结构与算法]代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 、 19.删除链表的倒数第N个节点 、面试题 02.07. 链表相交 、142.环形链表II

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

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

【思路】

画图后就容易理解了,别忘了定义临时变量保存要被丢掉的节点。借用卡哥的图来看一下:
来自代码随想录
注意:

  • 设置虚拟头结点可以方便的操作头结点
  • 注意设置临时变量保存要断开的节点
  • 画图!画图!画图!不画图很容易乱。

【代码】

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0); //虚拟头节点
        dummyHead->next = head;
        ListNode* cur=dummyHead;
        while(cur->next && cur->next->next) { //判断顺序不能混,一定cur->next不为空时,cur->next->next 才有意义
            ListNode* temp = cur->next;
            ListNode* temp1 = cur->next->next->next;
            cur->next = cur->next->next; //步骤一
            cur->next->next =temp; //步骤二
            temp->next = temp1; //步骤三
            cur = cur->next->next;
        }
        return dummyHead->next;
    }
};

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

题目链接: 19.删除链表的倒数第N个节点

【思路】

采用双指针进行操作,首先快指针先走n个节点,然后快慢指针同时前进,当快指针到达链表尾节点,即fast->next = Null,慢指针就指向了要删除的上一个节点

-我们要删除节点,需要知道它的上一个节点,才能操作

【代码】

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* cur = dummyHead;
        ListNode* pre = dummyHead;
        while (n--) {
            cur = cur->next;
        }
        while (cur->next != nullptr) {
            pre = pre->next;
            cur = cur->next;
        }
        ListNode* temp = pre->next;
        pre->next = pre->next->next;
        delete temp;
        return dummyHead->next;
    }
};

注意: C++不要忘记释放临时节点。

面试题 02.07. 链表相交

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

【思路】

链表的长度不同,所以需要先统计两个链表的长度,然后将指针向前移动长度之差个节点,然后两个节点同时向前移动,指针相等时,即为相交,返回指针。

来自代码随想录
如图所示,首先设置curA指向链表A的头结点,curB指向链表B的头节点,然后将两个链表尾部对齐,curA移动到和curB对齐的位置,二者同时移动。

【代码】

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
         ListNode* curA = headA;
         ListNode* curB = headB;
         int sizeA = 0, sizeB = 0;
         while (curA != NULL) {
             curA = curA->next;
             sizeA++;
         }
         while (curB != NULL) {
             curB = curB->next;
             sizeB++;
         }
         curA = headA;
         curB = headB;
         
         //始终让curA指向较长的链表
         if (sizeA < sizeB) {
             swap (sizeA, sizeB);
             swap (curA, curB);
         }
         int n = sizeA - sizeB;
         while (n--) {
             curA = curA->next;
         }
         while (curA != NULL && curB != NULL) { //其实判断一个就行,因为最后剩的距离相等
             if (curA == curB) return curA;
             curA = curA->next;
             curB = curB->next;
         }
         return NULL;
    }
};

【注意】

  • 节点的值相等不代表节点相等,相交指的是同一块内存,也就是指针指向的地址相等。

142.环形链表II

题目链接: 142.环形链表II

【思路】

此题比较难理解,必须借助画图来理解。
首先定义一组快慢指针,快指针一次走两个节点,慢指针一次走一个节点,二者一定会在环内相遇,因为在环内,就是快指针相对一个节点一个节点追慢指针的一个过程。
来自代码随想录

  • 如果两个指针能够相遇,就一定证明有环,否则慢指针永远也追不上快指正。

在这里插入图片描述
相遇时: 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 ,
整理公式之后为如下公式:x = (n - 1) (y + z) + z
注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z
意味着:从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是环形入口的节点。
在相遇点定义一个index1,链表头部定义index2,两个指针同时向前移动,一次一个节点,在入口处相遇。

来自代码随想录

【代码】

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

此题值得好好回味

总结

  • 一定要动手画一画,模拟一下,尤其是链表问题
  • 删除链表需要找到前一个节点,并且不要忘记delete掉
  • 设置虚拟头节点操作头节点会方便许多
  • 注意空指针的情况,操作空指针会报错
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-10-31 12:25:10  更:2022-10-31 12:26:13 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 19:30:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码