LeetCode算法入门(第四十天)
链表
25.K个一组翻转链表
采用哑节点指向头节点,可以避免链表翻转之后,链表的头节点发生了变化,不知道返回哪个节点的问题。
class Solution {
public:
// 翻转一个子链表,并且返回新的头与尾
pair<ListNode*, ListNode*> myReverse(ListNode* head, ListNode* tail) {
ListNode* prev = tail->next;
ListNode* p = head;
while (prev != tail) {
ListNode* nex = p->next;
p->next = prev;
prev = p;
p = nex;
}
return {tail, head};
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
ListNode* pre = dummy;
while (head) {
ListNode* tail = pre;
//把链表节点按照 k 个一组分组
for (int i = 0; i < k; ++i) {
tail = tail->next;
if (!tail) {
return dummy->next;
}
}
ListNode* nex = tail->next; //暂存翻转前尾节点指向的节点
pair<ListNode*, ListNode*> result = myReverse(head, tail); //翻转
head = result.first;
tail = result.second;
// 把子链表重新接回原链表
pre->next = head;
tail->next = nex;
pre = tail;
head = tail->next;
}
return dummy->next;
}
};
143.重排链表
利用线性表可以下标访问的特点,直接按顺序访问指定元素,重建该链表。
/**
* 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:
void reorderList(ListNode* head) {
if(head == nullptr){
return;
}
vector<ListNode*> vec;
ListNode *node = head;
//将链表存入线性表中
while(node != nullptr){
vec.emplace_back(node);
node = node->next;
}
//从首尾开始取元素
int i = 0, j = vec.size() - 1;
while(i < j){
vec[i]->next = vec[j];
i++;
if(i == j){ //首尾指针相遇则退出
break;
}
vec[j]->next = vec[i];
j--;
}
vec[i]->next = nullptr;
}
};