基本思路是将头插法组织的链表重新进行一次头插 对尾插法组织的链表重新进行一次尾插
为没有头结点的链表添加头结点以维护需要返回的位置是非常常用的技巧
206 反转链表
class Solution {
public:
ListNode *headSolve(ListNode *head) {
ListNode *tHead = new ListNode(0);
while (head) {
ListNode *p = head->next;
head->next = tHead->next;
tHead->next = head;
head = p;
}
return tHead->next;
}
ListNode *tailSolve(ListNode *head) {
ListNode *cur = nullptr;
while (head) {
ListNode *p = head->next;
head->next = cur;
cur = head;
head = p;
}
return cur;
}
ListNode* reverseList(ListNode* head) {
// return headSolve(head);
return tailSolve(head);
}
};
对于翻转某一段的链表,思路和上面相同,只是要考虑维护头节点,且尾节点不为null
// 把头尾拿出来再处理的方法不表
92 反转链表 II
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode *tHead = new ListNode(0, head);
ListNode *pre = tHead;
int count = 1;
while (count != left) {
count ++;
pre = head;
head = head->next;
}
while (count != right) {
count ++;
ListNode *nxt = head->next;
ListNode *q = nxt->next;
nxt->next = pre->next;
pre->next = nxt;
head->next = q;
}
return tHead->next;
}
25 K 个一组翻转链表
对于k个一组翻转,很容易想到多次利用区间翻转进行求解,只需复用以上代码即可,但此种方法每次都需要重头结点开始遍历,寻找区间的头尾,造成了时间的浪费,时间复杂度约为nlogn,虽然力扣提交并无差异,但考虑数据量大的情况,需要考虑更优解
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode *tHead = new ListNode(0, head);
ListNode *pre = tHead;
int count = 1;
while (count != left) {
count ++;
pre = head;
head = head->next;
}
while (count != right) {
count ++;
ListNode *nxt = head->next;
ListNode *q = nxt->next;
nxt->next = pre->next;
pre->next = nxt;
head->next = q;
}
return tHead->next;
}
int getLen(ListNode *head) {
ListNode *p = head;
int len = 0;
while (p) {
p = p->next;
len ++;
}
return len;
}
ListNode* reverseKGroup(ListNode* head, int k) {
int len = getLen(head);
for (int i = 1; i + k - 1 <= len; i += k) {
head = reverseBetween(head, i, i + k - 1);
}
return head;
}
考虑从头开始一直往后找结点,将区间的首位结点提取出来进行翻转,复杂度为2*n
//左闭右开
ListNode *flip(ListNode *left, ListNode *right) {
ListNode *cur = right;
while(left != right) {
ListNode *p = left->next;
left->next = cur;
cur = left;
left = p;
}
return cur;
}
ListNode* reverseKGroup(ListNode* head, int k) {
ListNode *tHead = new ListNode(0, head);
ListNode *pre = tHead;
int count = 0;
while (head) {
count++;
ListNode *left = head;
ListNode *right;
for (int i = 0; i < k - 1 && head; i++) {
head = head->next;
}
if (head) {
right = head->next;
head = right;
} else {
return tHead->next;
}
pre->next = flip(left, right);
pre = left;
}
return tHead->next;
}