解决这道题需要三个步骤:
- 找到需要反转的第一个节点。可以通过头节点前进m-1步,找到反转开始的位置。
- 将需要反转的部分进行反转。参考Leetcode 206:反转链表。
- 将反转部分与剩余部分进行链接。其中分为两种情况,m=1与m>1。当m=1时,仅需要将反转部分反转前的头节点的next指向反转部分反转前尾节点的后继,新链表的头节点为反转部分反转前的尾节点。当m>1时,还需要将反转部分反转前头节点的前驱的next指向反转部分反转前的末节点,新链表的头节点仍为原链表的头节点。假设m=2,n=4,其中有以下几个关键节点:
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
int change_len = n - m + 1; //需要反转的长度
ListNode *pre_head = NULL; //反转部分的前驱节点
ListNode *result = head;
while(head && --m) //移动到反转的开始位置
{
pre_head = head;
head = head->next;
}
ListNode *tmp = head; //反转部分头节点,即反转后的尾节点
ListNode *new_head = NULL;
while(head && change_len) //反转部分链表
{
ListNode *next = head->next;
head->next = new_head;
new_head = head;
head = next;
change_len--;
}
tmp->next = head; //反转后的尾节点链接反转段的后一个节点
if (pre_head) //前驱节点不为空,说明m>1
{
pre_head->next = new_head; //反转部分的前驱节点连接反转后的头节点
}
else
{
result = new_head;
}
return result;
}
};
解决这个问题需要两个步骤:
- 使用快慢指针判断链表是否存在环。慢指针在链表中一次走一步,快指针一次走两步,如果链表中存在环,快慢指针总会到达同一个节点meet。
- 从链表的头节点head以及meet同时出发,两个指针速度相同,相遇时即为环的起点。
设绿色部分为a,蓝色部分为b,黄色部分为c。可知快指针走过的路程时慢指针的两倍,即2(a+b)=a+b+c+b,可以得到a=c,所以head节点与meet节点相遇时即为环的起点。
class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode* fast = head; ListNode* slow = head; ListNode* meet = NULL; while(fast) { fast = fast->next; slow = slow->next; if(!fast) return NULL; else fast = fast->next; if(fast == slow) { meet = fast; break; } } if (meet == NULL) return NULL; while(head && meet) { if(head == meet) return meet; head = head->next; meet = meet->next; } return NULL; } };
解决这个问题需要三个步骤:
- 复制节点,将复制的节点连接到原节点之后,原节点的next连接到复制的节点之后。
- 复制随机指针。
- 分离节点。
class Solution {
public:
Node* copyRandomList(Node* head)
{
if (!head) return nullptr;
Node* curnode = head;
while (curnode) //遍历原链表复制节点
{
Node* copy = new Node(curnode->val, curnode->next, nullptr);
Node* tmp = curnode->next;
curnode->next = copy;
curnode = tmp;
}
curnode = head;
while (curnode) //遍历链表连接复制节点的随机指针
{
if (curnode->random)
curnode->next->random = curnode->random->next;
curnode = curnode->next->next;
}
curnode = head;
Node* new_head = head->next; //复制节点的头节点
while (curnode->next) //分离节点
{
Node* tmp = curnode->next;
curnode->next = curnode->next->next;
curnode = tmp;
}
return new_head;
}
};
解决此题的思路类似于归并排序,对于两个排序列表的合并可以参考Leetcode 21:合并两个有序链表,在对k个排序链表进行合并时,可以通过分治的思想,对k个链表两两进行合并。
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
if(lists.size() == 0)
return NULL;
if(lists.size() == 1)
return lists[0];
if(lists.size() == 2)
return mergeTwoLists(lists[0],lists[1]);
int size = lists.size();
int mid = size/2;
vector<ListNode*> tmp1;
vector<ListNode*> tmp2;
for(int i = 0;i < mid;i++)
{
tmp1.push_back(lists[i]);
}
for(int i = mid;i < size;i++)
{
tmp2.push_back(lists[i]);
}
ListNode* l1 = mergeKLists(tmp1);
ListNode* l2 = mergeKLists(tmp2);
return mergeTwoLists(l1,l2);
}
ListNode* mergeTwoLists(ListNode* list1,ListNode* list2) //合并两个有序链表
{
ListNode new_head(0);
ListNode* prenode = &new_head;
while(list1&&list2)
{
if(list1->val>list2->val)
{
prenode->next=list2;
list2 = list2->next;
}
else
{
prenode->next = list1;
list1 = list1->next;
}
prenode = prenode->next;
}
if(list1) //如果list1不为空,将剩余节点连接在已合并的链表之后
prenode->next = list1;
if(list2) //list2同理
prenode->next = list2;
return new_head.next;
}
};
原文地址:https://www.cnblogs.com/gcheeze/p/11006968.html
时间: 2024-11-08 20:51:08