一、92.反转链表II
思路即分别定位第m个和第n个结点(若不存在,则直接返回首结点),从m到n-1,摘下每一个结点,并插入到第n个结点之后
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode FakeHead(0),*pm,*pn,*ptr;
int i;
FakeHead.next=head;
ptr=&FakeHead;
if(m>=n)
return head;
for(i=1;i<m;i++)
{
if(ptr==NULL)
return head;
ptr=ptr->next;
}
pm=ptr;
while(i<=n)
{
if(ptr==NULL)
return head;
ptr=ptr->next;
i++;
}
pn=ptr;
while(pm->next!=pn)
{
ptr=pm->next;
pm->next=ptr->next;
ptr->next=pn->next;
pn->next=ptr;
}
return FakeHead.next;
}
};
二、25.K个一组翻转链表
思路类似第92题,把每个ak+1当作m,每个ak当作n即可
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {
if(head==NULL) return head;
struct ListNode FakeHead(0);
struct ListNode *TempHead=&FakeHead,*NextTempHead=FakeHead.next,*ptr,*pk=&FakeHead;
FakeHead.next=head;
int cnt=0;
while(pk!=NULL)
{
NextTempHead=TempHead->next;
cnt=0;
while(pk!=NULL && cnt<k)
{
pk=pk->next;
cnt++;
}
if(pk==NULL || cnt<k)
break;
while(TempHead->next!=pk)
{
ptr=TempHead->next;
TempHead->next=TempHead->next->next;
ptr->next=pk->next;
pk->next=ptr;
}
TempHead=NextTempHead;
pk=TempHead;
}
return FakeHead.next;
}
};
三、23.合并K个排序链表
思路1.基于21题合并两个排序链表,K个排序链表的合并可通过两两合并来实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode FakeHead(0),*p=l1,*q=l2,*ptr,*temp;
ptr=&FakeHead;
while(p!=NULL && q!=NULL)
{
temp=(ListNode*)malloc(sizeof(ListNode*));
if(p->val<=q->val)
{
temp->val=p->val;
p=p->next;
}
else
{
temp->val=q->val;
q=q->next;
}
ptr->next=temp;
ptr=ptr->next;
}
if(p!=NULL)
ptr->next=p;
if(q!=NULL)
ptr->next=q;
return FakeHead.next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.empty())
return NULL;
while(lists.size()>1)
{
lists.push_back(mergeTwoLists(lists[0], lists[1]));
lists.erase(lists.begin());
lists.erase(lists.begin());
}
return lists.front();
}
};
思路2.参考了这篇博客,从合并两个排序链表受到启发,构造新链表时,每次取用的结点为两个链表尚未取过的结点中,值较小的一个,因此可以利用优先队列来维护候选结点(用这种方法应当注意空链表的处理)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
struct cmp
{
bool operator() (const ListNode* a,const ListNode* b)
{
return a->val>b->val;
}
};
ListNode* mergeKLists(vector<ListNode*>& lists) {
priority_queue<ListNode*, vector<ListNode*>, cmp> q;
ListNode *ans,*ptr;
for(auto item:lists)
if(item)
q.push(item);
if(q.empty())
return NULL;
ans=q.top();
q.pop();
if(ans->next)
q.push(ans->next);
ptr=ans;
while(!q.empty())
{
ptr->next=q.top();
q.pop();
ptr=ptr->next;
if(ptr->next)
q.push(ptr->next);
}
ptr->next=NULL;
return ans;
}
};