160.两个链表的交点
leetcode160
解题思路:
设 A 的长度为 a + c,B 的长度为 b + c,其中 c 为尾部公共部分长度,可知 a + c + b = b + c + a。同样的距离,同样的速度,则一定可以找到公共节点。
当访问 A 链表的指针访问到链表尾部时,令它从链表 B 的头部开始访问链表 B;同样地,当访问 B 链表的指针访问到链表尾部时,令它从链表
A 的头部开始访问链表 A。这样就能控制访问 A 和 B 两个链表的指针能同时访问到交点。如果不存在交点,那么 a + b = b + a,以下实现代码中 l1 和 l2 会同时为 null,从而退出循环。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *l1=headA,*l2=headB;
while(l1!=l2){
l1=(l1==NULL)?headB:l1->next;
l2=(l2==NULL)?headA:l2->next;
}
return l1;
}
};
206.反转链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
//迭代
// ListNode *pre=NULL;
// ListNode *cur=head;
// while(cur!=NULL){
// ListNode *tmp=cur->next;
// cur->next=pre;
// pre=cur;
// cur=tmp;
// }
// return pre;
//递归
if(head==NULL||head->next==NULL) return head;
ListNode *next=head->next;
ListNode *newhead=reverseList(next);
next->next=head;
head->next=NULL;
return newhead;
}
};
21.合并两个有序链表
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
//递归问题
// if(l1==NULL) return l2;
// if(l2==NULL) return l1;
// if(l1->val<l2->val){
// l1->next=mergeTwoLists(l1->next,l2);
// return l1;
// }else{
// l2->next=mergeTwoLists(l1,l2->next);
// return l2;
// }
//暴力解法
ListNode *head=new ListNode(-1);
ListNode *h=head;
while(l1!=NULL&&l2!=NULL){
if(l2->val<l1->val){
h->next=l2;
l2=l2 ->next;
}else{
h->next=l1;
l1=l1->next;
}
h=h->next;
}
h->next=(l1==NULL)?l2:l1;
return head->next;
}
};
**
2.链表相加
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
//虚拟头节点
ListNode *head=new ListNode(-1);
ListNode *h=head;
int sum=0;//两个链表的和
bool carry=false;//进位
while(l1!=NULL||l2!=NULL){
sum=0;
if(l1!=NULL){
sum+=l1->val;
l1=l1->next;
}
if(l2!=NULL){
sum+=l2->val;
l2=l2->next;
}
if(carry){
sum+=1;
}
h->next=new ListNode(sum%10);
h=h->next;
carry=sum>=10?true:false;
}
//如果最后有进位,末尾补1;[添加链接描述](https://leetcode-cn.com/problems/add-two-numbers/)
if(carry){
h->next=new ListNode(1);
}
return head->next;
}
};
链表中环的入口节点
题目描述:
给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解题思路:
设置双指针,一个慢指针,一个快指针,慢指针一次移动一步,快指针一次移动两步,如果链表中存在环,则一定会相遇,当第一次相遇后,将快指针设置为头节点,然后快指针和慢指针每次移动一步,则下次相遇一定是环的入口节点;
代码实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* EntryNodeOfLoop(ListNode* pHead)
{
if(pHead==nullptr||pHead->next==nullptr) return nullptr;
ListNode *p1=pHead;
ListNode *p2=pHead;
//快指针和快指针->next不为空;
while(p2&&p2->next){
p1=p1->next;
p2=p2->next->next;
if(p1==p2) break;
}
//if(!p2||!p2->next) return nullptr;
p2=pHead;
while(p2!=p1){
p2=p2->next;
p1=p1->next;
}
return p1;
}
};