专题:链表
题目:两两交换链表中的节点
给定一个链表,两两交换其中相邻的节点,并返回交换后的链表。
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
例如:
题目分析
要两两交换链表中的结点,怎么操作呢?我们使用cur指向虚拟头节点,对虚拟头节点的后两个结点进行翻转操作。然后cur往后移动两个位置,继续操作当前结点的后两个结点。依次循换直到全部的结点翻转过来直到cur的->next或cur->next->next=NULL循环结束(如果cur->next为空的话,说明cur就是最后一个结点,不要在翻转,如果cur->next->next =nullptrd的话说明cur后面只有一个结点了,也不用翻转了)。具体操作:先得用临时指针temp 和temp1保存 head 和 下下一结点,因为要改变dummyhead->next 的指向 不保存head的话,就找不到了。因为要改变下一结点的指向,不保存下下一结点指针的话,也就找不见了。保存了之后。然后依照①②③的顺序去执行。然后更新cur=cur->next->next;
细节注意:
注意:
使用虚拟头结点,就可以满足对链表每个结点的统一操作;
判断条件是链表结点有后两个结点才会满足翻转的条件。怎么判断呢?(cur->next != nullptr || cur->next->next != nullptr) ;
在执行翻转操作时,铭记一旦执行一个翻转的步奏,那么链表结点就会产生一次变化。所以要根据最新的链表信息来写后面的语句。
代码实现:
题目:删除链表的倒数第N个结点
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
输入:head = [1,2,3,4,5], n = 2 输出:[1,2,3,5]
输入:head = [1], n = 1 输出:[ ]
题目分析:
快慢指针法:快慢指针fast slow 指向head;先让快指针走到第n个结点。然后快指针不为空的情况下,快慢指针都往后走,直到快指针指向空。此时慢指针指向的就是,倒数第n个结点的前一个结点,然后操作倒数第n个结点的前一个结点,指向倒数第n个结点的下一个结点。然后完成了删除倒数第n个结点的操作。
细节注意
这个题目,让我第一次发现,编译器是一个老实人,不管你用心写的,还是随意写的,编译器就只会老老实实的根据你的代码去做事情。所以一旦发现编译器,没执行通过。不要怀疑老实本分的编译器,好好看看自己的代码,找到问题,修改正确。编译器就能通过。
注意事项:链表的节点的把握,快慢指针指向dummyhead 还是 dummyhead->next.怎么设计才能让fast走到null的同时,slow刚好到倒数第n个结点的前一个结点位置。这个必须明白。
如果 fast slow 都指向 dummyhead 那么 此时判断条件就是 fast->next != nullptr,fast=fast->next;slow=slow->next;
如果 slow 指向 dummyhead ,fast 指向 dummyhead->next ;那么 此时判断条件就是 fast!= nullptr,fast=fast->next;slow=slow->next;
记住要让fast先走n步;
代码实现
题目:链表相交
给你两个单链表的头节点
headA
和headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回null
。
题目分析:
首先计算两个链表的长度,长的减短的,算出个数差,然后定义两个指针,分别指向这两个链表。先让长的链表的指针,往后走他两的差的步子,然后他两一起往后走,如果能遇到即他两个指针相等,说明就找到了相遇的地方。如果指针一直都不相等,说明没有相交的结点。
细节注意:
思想简单,但是要
一定注意,在统计完链表长度之后,一定要让cura,curb指向原来的链表头。
之后交换的时候,目的就是为了,明确让cura去指向长的链表,curb去指向短的链表。方便后面减法操作。
代码实现:
题目:循环链表
题意: 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
为了表示给定链表中的环,使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。
题目解析
首先你要深刻理解,原理!!!
fast指针一次走两步的条件是(fast!=nullptr && fast->next != nullptr)保证了这个条件,那么fast->next->next这个位置,可以有值,也可以是NULL。没关系,都可以让fast去指向这个位置即 fast-->next = fast->next->nextr->next;
两个指针fast 和 slow 都指向head节点,然后fast一次走两步,slow一次走一步。然后如果有环的话,fast ,slow 肯定就相遇了。因为如果有环的话,fast最后在环里面一次走两步,slow在环里面一次走一步,那么相当于slow在环里面不动,fast一次走一步,那么fast肯定可以和slow相遇。一旦相遇就说明肯定有环。
此时完成了是否有环的判断!!!!!!!
还有就是如何寻找环的入口????
根据公式计算,最终得到当n=1时,x=z;即head到环入口的距离等于fast和slow相遇点到环入口的距离。根据这个条件,我们设置两个指针index1,index2.一个指向head,一个指向fast,slow相遇点。然后while(index1 != index2)就都往后走一步,直到index1 = index2 返回index2;也就是环的入口。
由题意得:2(x+y) = x+y+n(z+y)
得: x+y =n(z+y)
x = nz +(n-1)y
当n=1时,得 x=z;
这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。
代码实现:
一个关键点:对于index1和index2,这个点。要在if条件里面就去定义它,执行它。在一个大括号里面定义的变量,在大口号外面使用不了????对的!!认真思考!!!
录友告诉我,大括号里面定义的变量,出了大括号就不能使用了,是吧。
答:变量只在定义及“}"之前有效。 一起学习,就是快乐!!!!
今天,在训练营里面提问,录友回答了我的疑问,让人感觉很爽!!!
一起学习是一件狠狠快乐的事情!!!!!!!!!!!!1