一、返回链表倒数第k个节点
. - 力扣(LeetCode)
本体思路参展寻找中间节点的方法,寻找中间节点是定义快慢指针,快指针每次走两步,慢指针每次走一步,当快指针为空或者快指针的下一个节点是空时,此时的慢指针指向的节点就是中间节点;并且此时的快指针和慢指针之间的节点个数就是整个链表的一半;
据此同理,可以定义快慢指针,使得快指针走到尾的时候,与慢指针之间的差距恰好是k个节点,那么此时的慢指针就是题中要求的节点;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
int kthToLast(struct ListNode* head, int k){
struct ListNode* slow=head,*fast=head;
while(k--)
{
fast=fast->next;
}
while(fast)
{
slow=slow->next;
fast=fast->next;
}
return slow->val;
}
二、链表的回文结构
链表的回文结构_牛客题霸_牛客网
回文结构即使对称的;本题思路是先利用快慢指针找到中间节点,之后再从中间节点开始逆置此节点之后的链表,得到一条新的链表;之后再从原本的链表的头节点和这条新链表的头节点开始一一比较,若是val值都相同则说明这个链表是回文结构;
当链表是奇数个时,新链表多出一个节点,但是不影响代码的正常运行,因为原链表中中间节点的前一个节点的指向还是新链表中作为尾节点的之前的中间节点,新链表的倒数第二个指针指向的也是这个节点,所以最后一次循环的时候其实是同一个节点在比较。
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
bool chkPalindrome(ListNode* A) {
// write code here
//找到中间节点
ListNode* slow=A;
ListNode* fast=A;
while(fast && fast->next)
{
slow=slow->next;
fast=fast->next;
}
ListNode* mid=slow;
//对从中间节点向后的节点组成的链表进行逆置操作
ListNode* newhead=NULL;
ListNode* cur=mid;
while(cur)
{
ListNode* next=cur->next;
cur->next=newhead;
newhead=cur;
cur=next;
}
//开始从头比较,若是都相等,那么就是回文结构
ListNode* head=A;
while(head && newhead)
{
if(head->val!=newhead->val)
{
return false;
}
head=head->next;
newhead=newhead->next;
}
return true;
}
};
三、相交链表
. - 力扣(LeetCode)
本题思路:首先判断两条链表是否相交,只需要判断尾节点的地址是否相同就行了,因为当两条链表相交时,无论从哪个节点开始相交起,尾节点的地址一定相同;反之,若是尾节点的地址不相同,那么这两条链表一定不相交;
在已经知道了两条链表相交的情况下如何寻找开始相交的节点?先计算出两条链表的长度,再计算出长度差,之后让长的链表先走这个长度差的节点,此时长的链表和短的链表之后的节点个数就相同了,此时开始一起遍历长链表和短链表,在遍历过程中若长链表和短链表的某一个节点的地址相同,就跳出循环,此时的节点就是开始相交的节点;
注意本题的比较不能用val值,因为两条链表中不同的地址的节点可能含有相同的val值;这时会造成混淆。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if(headA==NULL || headB==NULL)
{
return NULL;
}
struct ListNode* tailA=headA;
struct ListNode* tailB=headB;
int lenA=1;
int lenB=1;
while(tailA->next)
{
tailA = tailA->next;
lenA++;
}
while(tailB->next)
{
tailB = tailB->next;
lenB++;
}
if(tailA!=tailB)
{
return NULL;
}
int gap=abs(lenA-lenB);
struct ListNode* longlist=headA;
struct ListNode* shortlist=headB;//先假设A更长
if(lenB>lenA)
{
longlist=headB;
shortlist=headA;
}//若是B长就进入该语句,改变更长链表指向的对象,反之则假设成立
while(gap--)
{
longlist=longlist->next;
}
while(longlist != shortlist)
{
longlist=longlist->next;
shortlist=shortlist->next;
}
return longlist;
}