Leetcode24. 两两交换链表中的节点
通过pre和p指针,将p和p->next交换顺序
struct ListNode* swapPairs(struct ListNode* head){
//新建虚拟头节点
struct ListNode* ahead=(struct ListNode *)malloc(sizeof(struct ListNode));
ahead->next=head;
//双指针从虚拟头节点开始
struct ListNode* pre=ahead;
struct ListNode* p=ahead->next;
//通过pre和p指针,将p和p->next交换顺序
while(pre&&p&&p->next){
pre->next=p->next;
p->next=pre->next->next;
pre->next->next=p;
//交换后下一次的pre为新的p
pre=p;
p=pre->next;
}
return ahead->next;
}
Leetcode19. 删除链表的倒数第 N 个结点
建立虚拟头节点,将快指向虚拟头节点,慢指针指向虚拟头节点的下一个。
先将快指针向后移动n个,然后快慢指针同时向后移动,当快指针到达链表末尾的时候,快指针达到倒数第n个位置的前一个,然后删除慢指针下一个即满足要求。
struct ListNode* removeNthFromEnd(struct ListNode* head, int n){
struct ListNode* ahead=(struct ListNode*)malloc(sizeof(struct ListNode));
ahead->next=head;
struct ListNode* pre=ahead;
struct ListNode* p=ahead->next;
int i;
for(i=0;i<n;i++){
p=p->next;
}
while(p){
pre=pre->next;
p=p->next;
}
pre->next=pre->next->next;
return ahead->next;
}
Leetcode面试题 02.07. 链表相交
代码不难,但是容易出错
统计链表长度时,注意i,j初始为0。
一般用新设的指针pApB循环统计,尽量不要改变头指针headAheadB的指向。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
int i=0,j=0;
struct ListNode* pA=headA;
struct ListNode* pB=headB;
//计算链表A、B的长度
while(pA){
pA=pA->next;
i++;
}
while(pB){
pB=pB->next;
j++;
}
pA=headA;
pB=headB;
//控制长的链表的指针P先向后移动,使链表一样长
if(i>j){
for(int k=0;k<i-j;k++){
pA=pA->next;
}
}else if(j>i){
for(int k=0;k<j-i;k++){
pB=pB->next;
}
}
//找到相交的起始节点
while(pA){
if(pA==pB){
return pA;
}
pA=pA->next;
pB=pB->next;
}
return NULL;
}
Leetcode142. 环形链表 II
快慢指针,从同一个起点出发,慢指针一次一步,快指针一次两步,若能相遇则代表有环。
从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是环形入口的节点。
struct ListNode *detectCycle(struct ListNode *head) {
struct ListNode *pre;
struct ListNode *p;
pre=head;
p=head;
while(p&&p->next){
pre=pre->next;
p=p->next->next;
//相遇代表有环
if(pre==p){
//求入口
struct ListNode* index1 = p;
struct ListNode* index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index2;
}
}
return NULL;
}