链表
1.链表反转
ListNode* ReverseList(ListNode* pHead) {
ListNode *pre=nullptr
ListNode*cur=pHead
ListNode*nex=nullptr
while(cur)
{
nex=cur->next
cur->next=pre
pre=cur
cur=nex
}
return pre
}
2.链表内指定区间反转
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head==NULL||head->next==NULL||m==n) return head
struct ListNode* p
struct ListNode* q
struct ListNode* l
l = (struct ListNode*)malloc(sizeof(struct ListNode))
l->next = head
p = q = l
for(int i =1
p = p->next
for(int i = 1
q = q->next
struct ListNode* p1 = p->next
struct ListNode* p2 = p1->next
p->next = q
p1->next = q->next
while(p2!=q){ //反转节点
p = p2->next
p2->next = p1
p1 = p2
p2 = p
}
p2->next = p1
return l->next
}

3.链表内每k个节点为一组反转
ListNode* reverseKGroup(ListNode* head, int k) {
if(k<=1) return head
if(!head) return head
ListNode *left=head
ListNode*right=head
for(int i=0
{
if(!right) return head
right=right->next
}
ListNode* node=reverseLink(left,right)
left->next=reverseKGroup(right, k)
return node
}
ListNode* reverseLink(ListNode* left,ListNode* right)
{
ListNode* pre = nullptr
ListNode *next = nullptr
while (left != right)
{
next = left->next
left->next = pre
pre = left
left = next
}
return pre
}
4.合并两个排序的链表
ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
{
ListNode *vhead = new ListNode(-1)
ListNode *cur = vhead
while (pHead1 && pHead2) {
if (pHead1->val <= pHead2->val) {
cur->next = pHead1
pHead1 = pHead1->next
}
else {
cur->next = pHead2
pHead2 = pHead2->next
}
cur = cur->next
}
cur->next = pHead1 ? pHead1 : pHead2
return vhead->next
}
5.合并k个已排序的链表,返回一个升序的链表
时间复杂度O(nlogn)
ListNode *mergeKLists(vector<ListNode *> &lists) {//传入参量是一个存放k个链表的容器
priority_queue<int,vector<int>,greater<int>> q
for(int i=0
{
ListNode *t=lists[i]
while(t)
{
q.push(t->val)
t=t->next
}
}
ListNode *head=new ListNode(0)
ListNode* p=head
while(!q.empty())//构造新链表
{
p->next=new ListNode(q.top())
q.pop()
p=p->next
}
return head->next
}
6.判断链表中是否有环
思路:快慢指针法,快指针每次走两步,慢指针每次走一步,如果相遇则有环
bool hasCycle(ListNode *head) {
if(head==nullptr) return false
ListNode * fast = head
ListNode * slow = head
while(fast&&fast->next)//循环条件
{
fast=fast->next->next
slow=slow->next
if(fast==slow)
return true
}
return false
}
7.链表中环的入口节点
思路:快慢指针法,快指针速度是慢指针的两倍,快慢指针第一次相遇时快指针所走路程是慢指针的两倍,此时让快指针回到头结点,速度和慢指针相同,再次相遇的节点就是环的入口节点。
ListNode* EntryNodeOfLoop(ListNode* pHead) {
ListNode * fast = pHead
ListNode * slow = pHead
while(fast&&fast->next)//循环条件
{
fast=fast->next->next
slow=slow->next
if(fast==slow) break
}
if(!fast||!fast->next) return nullptr
fast=pHead
while(fast!=slow)
{
fast=fast->next
slow=slow->next
}
return fast
}
链表中的倒数k个节点
思路:快慢指针法,快指针先走k步,快慢指针同时开始走,当快指针走到终点时,慢指针所指的就是链表的倒数第k个节点。
ListNode* FindKthToTail(ListNode* pHead, int k) {
ListNode * fast=pHead
ListNode * slow = pHead
for(int i=0
{
if(!fast) return nullptr
fast=fast->next
}
while(fast)
{
slow=slow->next
fast=fast->next
}
return slow
}
删除链表的倒数第n个节点
格外注意边界条件的判断
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(!head) return nullptr
ListNode * fast = head
ListNode * slow = head
ListNode * p=new ListNode(0)
p->next=head
for(int i = 0
{
fast=fast->next
}
if(!fast) //如果快指针不存在,说明要删除的是头结点
{
p->next=p->next->next
return p->next
}
while(fast->next!=nullptr)//找到倒数第n+1个节点
{
slow=slow->next
fast=fast->next
}
slow->next=slow->next->next
return head
}
10.两个链表的第一个公共节点
描述:输入两个无环的单向链表,找到第一个公共节点并返回,如果没有公共节点,返回空指针
ListNode* FindFirstCommonNode( ListNode* pHead1, ListNode* pHead2) {
ListNode *ta = pHead1, *tb = pHead2
while (ta != tb) {
ta = ta ? ta->next : pHead2
tb = tb ? tb->next : pHead1
}
//若无公共部分,两指针都走了m+n(m+n为两表长之和)的长度,同时指向空,不满足循环条件,跳出循环
return ta