给定一个链表,判断链表中是否有环。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
//快慢指针
ListNode* fast=head;
ListNode* slow=head;
while(fast && fast->next){
fast=fast->next->next; //快指针一次走两步
slow=slow->next; //慢指针一次走一步
if(fast==slow) //如果有环一定会相遇
return true;
}
return false;
}
};
给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
//快慢指针,公式法
ListNode* fast=head;
ListNode* slow=head;
while(fast && fast->next){
fast=fast->next->next;
slow=slow->next;
if(fast==slow){ //相遇后,确定入环结点
ListNode* meet=slow;
ListNode* cur=head;
//找到入环结点:如图所示,因为 L=C-X,所以meet和cur会走相同的距离,一定会在入环点相遇
while(meet!=cur){
cur=cur->next;
meet=meet->next;
}
return cur;
}
}
return nullptr;
}
};
编写一个程序,找到两个单链表相交的起始节点。如果两个链表没有交点,返回 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* curA=headA;
ListNode* curB=headB;
int lenA=0,lenB=0;
if(headA==nullptr || headB==nullptr)
return nullptr;
while(curA && curA->next){
++lenA;
curA=curA->next;
}
while(curB && curB->next){
++lenB;
curB=curB->next;
}
if(curA!=curB)
return nullptr;
else{
ListNode* longlist=headA; //找到长的链表
ListNode* shortlist=headB;
if(lenA<lenB){
longlist=headB;
shortlist=headA;
}
int gap=abs(lenA-lenB);
while(gap--) //长的链表先走gap步
longlist=longlist->next;
while(longlist!=shortlist){ //然后一起走,直到相遇
longlist=longlist->next;
shortlist=shortlist->next;
}
return longlist;
}
}
};
给定一个头结点为 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* middleNode(ListNode* head) {
//双指针
ListNode* fast=head;
ListNode* slow=head;
while(fast && fast->next){
fast=fast->next->next;
slow=slow->next;
}
return slow;
}
};
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
/**
* 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* removeNthFromEnd(ListNode* head, int n) {
//双指针,让fast先走n步,然后一起走,直到走到末尾
//最后slow指向的是倒数第n个结点的**前一个结点**
//如果fast先走n-1步,然后一起走,则最后slow指向的是倒数第n个结点
ListNode* fast=head;
ListNode* slow=head;
ListNode* tmp=nullptr;
if(head==nullptr) //如果链表为空则返回
return nullptr;
while(n--) //快指针先走n步
fast=fast->next;
while(fast && fast->next){ //然后一起走
slow=slow->next;
fast=fast->next;
}
if(fast==nullptr){ //如果删除的是第一个结点
tmp=head;
head=head->next;
delete tmp;
}
else{ //如果删除的是其余结点
tmp=slow->next;
slow->next=tmp->next;
delete tmp;
}
return head;
}
};
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
/**
* 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* cur=head;
ListNode* pre=nullptr;
head=nullptr;
while(cur!=nullptr){
pre=cur;
cur=cur->next;
pre->next=head;
head=pre;
}
return head;
}
};
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
/**
* 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) {
ListNode* dummy=new ListNode(-1); //创建一个头结点
ListNode* pre=dummy;
while(l1 && l2){ //l1和l2都不为空时
if(l1->val<l2->val){
pre->next=l1;
l1=l1->next;
}
else{
pre->next=l2;
l2=l2->next;
}
pre=pre->next;
}
//合并后 l1 和 l2 最多只有一个还未被合并完,直接将链表末尾指向未合并完的链表即可
pre->next=(l1==nullptr ? l2 : l1);
return dummy->next;
}
};
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
/**
* 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* removeElements(ListNode* head, int val) {
//双指针
ListNode* cur=head; //指向当前结点
ListNode* pre=nullptr; //指向当前结点的前驱
if(head==nullptr) //处理第一个结点,若为空
return nullptr;
while(cur!=nullptr){ //遍历
if(head->val==val){ //处理第一个结点,若第一个结点要删除
head=cur->next;
delete cur;
cur=head;
}
else if(cur->val==val){ //删除
pre->next=cur->next;
delete cur;
cur=pre->next;
}
else{ //后移
pre=cur;
cur=cur->next;
}
}
return head;
}
};