11.随机链表的复制 138. 随机链表的复制 - 力扣(LeetCode) /* 解题思路: 此题可以分三步进行: 1.拷贝链表的每一个节点,拷贝的节点先链接到被拷贝节点的后面 2.复制随机指针的链接:拷贝节点的随机指针指向被拷贝节点随机指针的下一个位置 3.拆解链表,把拷贝的链表从原链表中拆解出来 */ class Solution { public: Node* copyRandomList(Node* head) { // 1.拷贝链表,并插入到原节点的后面 Node* cur = head; while(cur) { Node* next = cur
文章目录 我的困惑 存储数组的链表 设计优点 配备方法 ngx_list_create ngx_list_init 我的困惑 这个链表我很喜欢,且这个构想在我的脑子里面存在很久了,但是一直没去实现 说是查询效率比较高,又能比链表高到哪里去? 这些问题我一直没有想明白,所以就不冒冒失失去实现了。 今天我就来为这些问题,找到一个出路! ---- 存储数组的链表 typedef struct ngx_list_part_s ngx_list_part_t; //节点 /* 每个链表元素ngx_list_part_t又是一个数组,拥有连续的内存 设计优点 1、通用链表 2、小块的内存使用链表访问效率是低下的,使用数组通过偏移量来直接访问内存则要高 效得多。 ngx_list_create 被调用后至少会创建一个数组(不会创建空链表),其中包含n个大小为size字节的连续内存 块,也就是ngx_list_t结构中的part成员。
❣️1.题目 描述 现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。 ❣️2.解答 输入参数包括一个指向链表头节点的指针和一个分割值x。函数将链表分为两个部分,一个部分中的节点值小于x,另一个部分中的节点值大于等于x。最终返回分割后的链表头指针。 函数内部定义了4个指针变量head1,tail1,head2,tail2分别表示两个链表的头尾节点。 然后对输入的链表进行遍历,如果节点值小于x,则将其插入head1到tail1所表示的链表中;否则将其插入head2到tail2所表示的链表中。最后将两个链表连接起来,形成最终的分割链表。
题目 : 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。 headB = headB.next; } return headA; } } } 思路 将长度比较长的链表指针提前赶到短链表的头结点位置
2021-11-07:奇偶链表。给定一个单链表,把所有的奇数节点和偶数节点分别排在一起。请注意,这里的奇数节点和偶数节点指的是节点编号的奇偶性,而不是节点的值的奇偶性。请尝试使用原地算法完成。 答案2021-11-07: 自然智慧即可。拆分成两个链表,然后合并。 时间复杂度:O(N)。 额外空间复杂度:O(1)。 代码用golang编写。
链表中倒数第k个节点 输入一个链表,输出该链表中倒数第k个结点。 思路 简单思路: 循环到链表末尾找到 length 在找到length-k节点 需要循环两次。 本题目着重考察代码鲁棒性、容错率: 需要考虑head为null,k为0,k大于链表长度的情况 代码 function FindKthToTail(head, k) { if (! behind = behind.next; } } return (k <= index) && behind; } 合并两个有序链表 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。 链表头部节点比较,取较小节点。 小节点的next等于小节点的next和大节点的较小值。 如此递归。 返回小节点。 考虑代码的鲁棒性,也是递归的终止条件,两个head为null的情况,取对方节点返回。
在链表中,头节点是链表的第一个节点,尾节点是链表的最后一个节点。链表的遍历可以从头节点开始,依次访问每个节点,并根据指针关系跳转到下一个节点。链表的操作包括插入节点、删除节点、查找节点等。 }2.链表常用操作2.1 初始化链表1、自定义链表的初始化/* 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */// 初始化各个节点ListNode n0 = new ListNode(1) 3.常见链表类型常见链表类型包括:单向链表:每个节点只有一个指针,指向下一个节点。双向链表:每个节点有两个指针,一个指向前一个节点,一个指向后一个节点。 带头节点的链表:在链表头部添加一个空节点,作为链表的起点。带尾节点的链表:在链表尾部添加一个空节点,作为链表的终点。静态链表:使用数组来实现链表结构,节点间的指针用数组下标来表示。 不会浪费太多空间:由于链表只需要为实际存储的数据分配空间,因此不会浪费太多空间。同时,链表还可以通过链表节点池和内存池等方式管理内存,进一步减少空间浪费。链表相对于数组,没有固定大小的限制。
思路分析 那这道题呢比较简单的一种思路是这样的: 新建两个链表less和greater,遍历原链表将原链表中值小于X的结点尾插(题目要求不能改变原来的数据顺序)到less链表,将大于等于X的结点尾插到 greater链表,然后将两个链表合并:greater链接到less后面。 那么另外呢: 对于新建的链表我们可以选择不带哨兵位的头结点,也可以选择带哨兵位的头结点的链表。 但是,对于这道题来说建议大家选取带头结点的链表结构。 如果不带头的话,实现起来就会比较麻烦。 首先带头结点的话尾插的时候空表的情况不需要单独判断,另外如果出现链表结点的值都比给定的X大,那这样第一个链表就是空,如果有头结点的话,空表状态也有一个头结点,这里把第二个链表往第一个链表后面链接的时候也会很方便 4,那么这样的话我们返回的链表就是一个带环的链表,遍历的时候就会陷入死循环。
福哥答案2020-11-03: 1.输入链表头节点,奇数长度返回中点,偶数长度返回上中点 。 1.1.快慢指针。 1.2.单指针。 1.3.数组。 2.输入链表头节点,奇数长度返回中点,偶数长度返回下中点 。这道题是leetcode上的第876道题,叫【链表的中间节点】。 2.1.快慢指针。 2.2.单指针。 2.3.数组。 这道题是leetcode上的第876道题,叫【链表的中间节点】。 这道题是leetcode上的第876道题,叫【链表的中间节点】。 这道题是leetcode上的第876道题,叫【链表的中间节点】。
题目 输入一个链表,输出该链表中倒数第k个结点。 思路 ? 简单思路: 循环到链表末尾找到 length 在找到length-k节点 需要循环两次。 本题目着重考察代码鲁棒性、容错率: 需要考虑head为null,k为0,k大于链表长度的情况 代码 function FindKthToTail(head, k) { if (! 、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。 链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。 由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn
但是TLE了 重要的事情说三遍,数组写的不对,下面链表那个才对! num < pos) cout<<"get fail"<<endl; else cout<<b[pos]<<endl; } } return 0; } 那么下面是正确的链表解法 insert" ) ) { scanf( "%d%d", &a, &e ); /*判断插入位置是否合法,若a=Count+1,表示插入在链表尾部
#include <stdio.h> #include <stdlib.h> #include <string.h> struct node { int data; struct node *pNext; }; //新建node struct node * create_node(int data) { struct node *p = (struct node *) malloc (sizeof(struct node)); if(NULL == p) {
【Leetcode21】合并两个有序链表 1.链接 合并两个有序链表 2.题目再现 3.三指针尾插法 思路:创建一个新的链表,分别遍历两个链表,小的就尾插到新链表,然后指针向后走一步,直到有一方为空时就结束循环 ;结束循环后,判断哪个链表不为空,把不为空的尾插到新链表中去。 分表遍历两个链表,比较其值,小的尾插到新链表,并向后走一步(如果一样大,那么随便取哪一个都行); 4.结束循环后,判断哪个链表不为空,尾插到新链表。 【Leetcode160】相交链表 1.链接 相交链表 2.题目再现 3.解法 1.先分别遍历两个链表,记录下两个链表的长度; 2.如果两个链表尾节点的地址一样,则说明它们相交,否则不相交,(注意是地址不是值 ); 3.求出两个链表长度的差gap; 4.先让长的链表走差距步gap,短的链表先不动; 5.然后两个链表同时走一步,比较每走一步时两个链表当前节点的地址,如果一样,则说明找到了它们相交的起始位置
题目链接 相交链表 方法一:哈希集合 判断两个链表是否相交。使用哈希集合存储链表节点。 创建一个哈希Set集合。先将链表A中的节点放入这个集合中。 再遍历链表B。 pA 从链表 headA 的头部开始遍历,pB 从链表 headB 的头部开始遍历。 如果 pA 到达了链表 headA 的末尾(pA == null),就让它跳到链表 headB 的头部继续遍历。 当 pA 到达链表headA的末尾时,pA 被重置为链表headB的头部,这是为了让 pA 开始遍历链表headB。 类似地,当 pB 到达链表headB的末尾时,pB 被重置为链表headA的头部。 通过这种方式,两个指针在遍历完自己的链表后,会从对方的链表头开始遍历。 由于两个指针都会遍历两个链表的总长度,无论两个链表的长度是否相同,最终两个指针会在相交节点处相遇,或者同时到达链表的末尾(即没有相交节点的情况)。
在链表尾插入数据 list_add(10,list_head); list_add(11,list_head); list_add(12,list_head); list_add 删除节点 list_del(11,list_head); //4. 在链表尾插入数据 list_add(10,list_head); list_add(11,list_head); list_add(12,list_head); list_add 删除节点 list_del(11,list_head); //4. 添加链表节点*/ list_add(10,list_head); list_add(11,list_head); list_add(12,list_head); list_add
相交链表 题目描述 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 思路: 先分别遍历两个链表,得出两个链表的节点个数和两个链表节点数的差,再创建两个指针指向两个链表,让节点数较多的链表的指针先遍历这个差值的节点数,然后两个指针再同时遍历,当两个指针指向的节点的地址相同时 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果链表无环,则返回 null。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。
重排链表 题目描述 给定一个单链表 L 的头节点 head ,单链表 L 表示为: L0 → L1 → … → Ln-1 → Ln 请将其重新排列后变为: L0 → Ln → L1 → Ln-1 提示: 链表的长度范围为 [1, 5 * 104] 1 <= node.val <= 1000 方法一: 将链表的每一个节点存在数组里,然后用下标访问的方式,交叉连接。 ,然后将中点后的链表翻转成一个新的链表,最后将这个新链表和原链表切割掉中间节点之后的链表合并成一个新的链表,合并方式是交叉合并。 题目描述 给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。 请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
一、链式存储结构 - 链表 链式存储结构 就是 链表 LinkedList ; 链式存储结构 ( 链表 ) : 数据 存储在 节点 中 , 每个节点包含 数据值 和 指向下一个节点的指针 ; 通过节点之间的指针关系 Object data; // 指向下一个节点 Node next; // 指向上一个节点 Node last; } 二、链表分类 - 单链表 / 双链表 / 非循环链表 / 循环链表 单链表 与 双链表 : 单链表 : 上述链表是 单链表 , 单链表 只有一个指针 指向下一个节点 ; 双链表 : 还有一种链表是 双链表 , 双链表 有两个指针 , 一个指向下一个节点 , 一个指向上一个节点 ; 循环链表 : 如果 最后一个节点的指针 指向 第一个节点 , 那么这个链表就是循环链表 ; 链表可以分为以下四类 : 单链表 单循环链表 双链表 双循环链表 三、链表优缺点 链表 LinkedList 链表 LinkedList 缺点: 查询 性能低 : 如果要访问 链表中 指定位置的元素 , 需要从头节点开始遍历到目标位置 , 时间复杂度为O(n)。
题目链接 反转链表 方法一:迭代 循环从第二个节点开始。 首先判断若没节点head为null 或者 若只有一个节点。head.next = null。则返回head。 接下来 定义一个 cur 节点,指向链表的第二个节点。这个 cur 将用于遍历链表。 将当前 head 节点的 next 设为 null,因为它将成为反转链表的末尾节点。 之后 开始遍历链表并反转指针 1.ListNode curNext = cur.next; 保存cur.next的值,防止丢失。 2.cur.next = head 反转链表。 令cur.next指向前一个节点 3.head = cur 设置反转链表的头结点。 假设链表的其余部分已经被反转,现在应该如何反转它前面的部分?
题目传送门 方法一:将值复制到数组中后用双指针法 思路: 1.将链表的值赋值到顺序表当中。 2.使用双指针法,判断顺序表中的值是否是回文。 left++; right--; } return true; } } 方法二:使用栈 思路: 1.先将链表中的值全部入栈 2.遍历链表,若链表元素与栈顶元素相等,则出栈。 3.栈最后为空,返回true。栈不为空返回false。 反转后半部分链表。 判断是否回文。 恢复链表。 返回结果。 isPalindrome(ListNode head) { if (head == null) { return true; } // 找到前半部分链表的尾节点并反转后半部分链表