链表part02
24 两两交换链表中的节点
题目
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路
首先需要确定要设置那些指针,一个pre指针是必要的,因为两个节点交换位置后需要pre指针将它们和前面的节点连接起来,指向当前两个节点的指针是必要的(这里我用p和p->next指向当前要交换的两个节点),此外,还要用tempNode保存当前两个节点的下一个节点的指针,方便交换过两个节点后移动要交换的两个节点的指针进行下一组交换。
注:设置一个空的头结点,来统一处理起始节点
代码
ListNode* swapPairs(ListNode* head) {
if(head==nullptr||head->next==nullptr) return head;
ListNode *dummyNode=new ListNode(-1);
dummyNode->next=head;
ListNode *pre=dummyNode;
ListNode *p=head;
while(p!=nullptr&&p->next!=nullptr){
ListNode *tempNode=p->next->next;
pre->next=p->next;
p->next->next=p;
p->next=tempNode;
pre=p;
p=tempNode;
}
return dummyNode->next;
}
19 删除链表的倒数第N个节点
题目
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
思路
因为是单向链表,无法倒着遍历,只能使用双指针left和right,两个指针的距离是n,两个指针一起移动,当右边的指针移动到末尾时,左边的指针指向的结点就是目标节点。
当前在left指针的左边要设置一个pre指针,方便删除目标节点。
代码
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dummyNode=new ListNode(-1);
dummyNode->next=head;
ListNode *pre=dummyNode;
ListNode *left=head;
ListNode *right=head;
while((n--)&&right!=nullptr){
right=right->next;
}
while(right!=nullptr){
pre=pre->next;
left=left->next;
right=right->next;
}
pre->next=left->next;
return dummyNode->next;
}
面试题 02.07. 链表相交
题目
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
思路
先计算两个链表的长度,然后设置两个指针分别指向两个链表的头结点,然后让较长的那个链表的指针先移动(长度差)个单位,之后两个指针再一起移动,直到发现两个指针相同,就找到了交点。
代码
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int ALen=0, BLen=0;
ListNode *curA=headA, *curB=headB;
while(curA!=nullptr){
ALen++;
curA=curA->next;
}
while(curB!=nullptr){
BLen++;
curB=curB->next;
}
int ahead=abs(ALen-BLen);
bool flag=ALen>BLen?true:false;
while(ahead--){
if(flag) headA=headA->next;
else headB=headB->next;
}
while(headA!=nullptr){
if(headA==headB) return headA;
headA=headA->next;
headB=headB->next;
}
return nullptr;
}
142 环形链表II
题目
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
思路
这其实是一道数学题,代码随想录中的讲解很形象、细致:https://programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html#%E6%80%9D%E8%B7%AF
这里不作阐述。
代码
ListNode *detectCycle(ListNode *head) {
//思路:设置快慢指针slow和fast,slow一次走一步,fast一次走两步,两指针第一次相遇时,slow回到起点,fast变为一次走一步并继续走,slow和fast再次相遇时即为环的入口节点。
//题目中说head为链表的头节点,那就是head是不存放数据的?(看测试结果是没有头节点的)
if(head==nullptr||head->next==nullptr) return nullptr;
ListNode *slow=head, *fast=head;
while(1){
slow=slow->next;
if(slow==nullptr||fast==nullptr||fast->next==nullptr) return nullptr;
fast=fast->next->next;
if(slow==fast) break;
}
slow=head;
while(slow!=fast){
slow=slow->next;
fast=fast->next;
}
return slow;
}